/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
/** @file
 * This file is a query creator for skrooge
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgpredicatcreator.h"

#include <QDomDocument>
#include <QTableWidget>
#include <QCheckBox>
#include <QApplication>

#include "skgdocument.h"
#include "skgmainpanel.h"
#include "skgservices.h"
#include "skgcombobox.h"
#include "skgcalculatoredit.h"
#include "skgdateedit.h"
#include "skgruleobject.h"

SKGPredicatCreator::SKGPredicatCreator(QWidget* iParent, SKGDocument* document, const QString& attribute, bool iModeUpdate, const QStringList& iListAtt)
    : QWidget(iParent), m_updateMode(iModeUpdate), m_kValue1(NULL), m_kValue2(NULL), m_kAttributes(NULL)
{
    SKGServices::AttributeType attType = SKGServices::TEXT;
    if (document) attType = document->getAttributeType(attribute);

    // Build
    this->setAutoFillBackground(true);
    this->resize(491, 25);
    QHBoxLayout* horizontalLayout = new QHBoxLayout(this);
    horizontalLayout->setSpacing(2);
    horizontalLayout->setMargin(0);
    horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
    m_kOperator = new SKGComboBox(this);
    m_kOperator->setObjectName(QString::fromUtf8("kOperator"));
    m_kOperator->setSizeAdjustPolicy(KComboBox::AdjustToContentsOnFirstShow);
    QSizePolicy newSizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
    newSizePolicy2.setHorizontalStretch(0);
    newSizePolicy2.setVerticalStretch(0);
    newSizePolicy2.setHeightForWidth(m_kOperator->sizePolicy().hasHeightForWidth());
    m_kOperator->setSizePolicy(newSizePolicy2);

    horizontalLayout->addWidget(m_kOperator);
    int nbAtt = iListAtt.count();
    if (nbAtt) {
        m_kAttributes = new SKGComboBox(this);
        if (m_kAttributes) {
            m_kAttributes->setObjectName(QString::fromUtf8("kAttributes"));
            m_kAttributes->setMinimumSize(QSize(100, 0));
            m_kAttributes->setEditable(false);
            QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
            newSizePolicy.setHorizontalStretch(0);
            newSizePolicy.setVerticalStretch(0);
            newSizePolicy.setHeightForWidth(m_kAttributes->sizePolicy().hasHeightForWidth());
            m_kAttributes->setSizePolicy(newSizePolicy);

            horizontalLayout->addWidget(m_kAttributes);

            foreach(const QString & att, iListAtt) {
                if (document) m_kAttributes->addItem(document->getIcon(att), document->getDisplay(att), att);
            }
        }
    }
    if (attType == SKGServices::TEXT) {
        SKGComboBox* cmbVal1 = new SKGComboBox(this);
        if (cmbVal1) {
            cmbVal1->setObjectName(QString::fromUtf8("cmbVal1"));
            cmbVal1->setMinimumSize(QSize(100, 0));
            cmbVal1->setEditable(true);
            QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
            newSizePolicy.setHorizontalStretch(0);
            newSizePolicy.setVerticalStretch(0);
            newSizePolicy.setHeightForWidth(cmbVal1->sizePolicy().hasHeightForWidth());
            cmbVal1->setSizePolicy(newSizePolicy);

            horizontalLayout->addWidget(cmbVal1);
            m_kValue1 = cmbVal1;
        }
        SKGComboBox* cmbVal2 = new SKGComboBox(this);
        if (cmbVal2) {
            cmbVal2->setObjectName(QString::fromUtf8("cmbVal2"));
            cmbVal2->setMinimumSize(QSize(100, 0));
            cmbVal2->setEditable(true);
            QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
            newSizePolicy.setHorizontalStretch(0);
            newSizePolicy.setVerticalStretch(0);
            newSizePolicy.setHeightForWidth(cmbVal2->sizePolicy().hasHeightForWidth());
            cmbVal2->setSizePolicy(newSizePolicy);

            horizontalLayout->addWidget(cmbVal2);
            m_kValue2 = cmbVal2;
        }

        if (document) {
            QString realTable = "operation";
            QString realAtt = attribute;
            QString realCond = "";
            if (attribute == "t_REALCATEGORY") {
                realTable = "category";
                realAtt = "t_fullname";
            } else if (attribute == "t_ACCOUNT" || attribute == "t_TOACCOUNT") {
                realTable = "account";
                realAtt = "t_name";
            } else if (attribute == "t_UNIT") {
                realTable = "unit";
                realAtt = "t_name";
            } else if (attribute == "t_REALCOMMENT") {
                realTable = "suboperation";
                realAtt = "t_comment";
            } else if (attribute == "t_REALREFUND") {
                realTable = "refund";
                realAtt = "t_name";
            } else if (attribute == "t_PAYEE") {
                realTable = "payee";
                realAtt = "t_name";
            } else if (attribute.startsWith(QLatin1String("p_"))) {
                realTable = "parameters";
                realAtt = "t_value";
                realCond = "t_name='" % attribute.right(attribute.length() - 2) % '\'';
            }
            SKGMainPanel::fillWithDistinctValue(cmbVal1, document, realTable, realAtt, realCond);
            SKGMainPanel::fillWithDistinctValue(cmbVal2, document, realTable, realAtt, realCond);
        }
    } else  if (attType == SKGServices::INTEGER || attType == SKGServices::FLOAT) {
        SKGCalculatorEdit* cmbVal1 = new SKGCalculatorEdit(this);
        if (cmbVal1) {
            cmbVal1->setObjectName(QString::fromUtf8("cmbVal1"));
            cmbVal1->setMode(SKGCalculatorEdit::EXPRESSION);
            cmbVal1->setMinimumSize(QSize(100, 0));

            horizontalLayout->addWidget(cmbVal1);
            m_kValue1 = cmbVal1;
        }
        SKGCalculatorEdit* cmbVal2 = new SKGCalculatorEdit(this);
        if (cmbVal2) {
            cmbVal2->setObjectName(QString::fromUtf8("cmbVal2"));
            cmbVal2->setMode(SKGCalculatorEdit::EXPRESSION);
            cmbVal2->setMinimumSize(QSize(100, 0));

            horizontalLayout->addWidget(cmbVal2);
            m_kValue2 = cmbVal2;
        }
    } else  if (attType == SKGServices::DATE) {
        if (iModeUpdate) {
            SKGComboBox* cmbVal1 = new SKGComboBox(this);
            if (cmbVal1) {
                cmbVal1->setObjectName(QString::fromUtf8("cmbVal1"));
                cmbVal1->setMinimumSize(QSize(100, 0));
                cmbVal1->setEditable(true);
                QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
                newSizePolicy.setHorizontalStretch(0);
                newSizePolicy.setVerticalStretch(0);
                newSizePolicy.setHeightForWidth(cmbVal1->sizePolicy().hasHeightForWidth());
                cmbVal1->setSizePolicy(newSizePolicy);

                horizontalLayout->addWidget(cmbVal1);
                m_kValue1 = cmbVal1;
            }

            SKGComboBox* cmbVal2 = new SKGComboBox(this);
            if (cmbVal2) {
                cmbVal2->setObjectName(QString::fromUtf8("cmbVal2"));
                cmbVal2->setMinimumSize(QSize(100, 0));
                cmbVal2->setEditable(false);
                QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
                newSizePolicy.setHorizontalStretch(0);
                newSizePolicy.setVerticalStretch(0);
                newSizePolicy.setHeightForWidth(cmbVal2->sizePolicy().hasHeightForWidth());
                cmbVal2->setSizePolicy(newSizePolicy);
                cmbVal2->addItems(QStringList() << "YYYYMMDD" << "MMDDYYYY" << "DDMMYYYY"
                                  << "MM-DD-YY" << "DD-MM-YY" << "MM-DD-YYYY" << "DD-MM-YYYY" << "YYYY-MM-DD");

                horizontalLayout->addWidget(cmbVal2);
                m_kValue2 = cmbVal2;
            }
        } else {
            SKGDateEdit* cmbVal1 = new SKGDateEdit(this);
            if (cmbVal1) {
                cmbVal1->setObjectName(QString::fromUtf8("cmbVal1"));
                cmbVal1->setMinimumSize(QSize(100, 0));

                horizontalLayout->addWidget(cmbVal1);
                m_kValue1 = cmbVal1;
            }

            SKGDateEdit* cmbVal2 = new SKGDateEdit(this);
            if (cmbVal2) {
                cmbVal2->setObjectName(QString::fromUtf8("cmbVal2"));
                cmbVal2->setMinimumSize(QSize(100, 0));

                horizontalLayout->addWidget(cmbVal2);
                m_kValue2 = cmbVal2;
            }
        }
    } else  if (attType == SKGServices::BOOL || attType == SKGServices::TRISTATE) {
        QCheckBox* cmbVal1 = new QCheckBox(this);
        if (cmbVal1) {
            cmbVal1->setObjectName(QString::fromUtf8("cmbVal1"));
            cmbVal1->setMinimumSize(QSize(100, 0));
            cmbVal1->setTristate(attType == SKGServices::TRISTATE);

            horizontalLayout->addWidget(cmbVal1);
            m_kValue1 = cmbVal1;
        }
    }

    // Fill combo boxes
    m_kOperator->clear();
    m_kOperator->addItem("" , "");

    if (m_kValue1) m_kValue1->installEventFilter(this);
    if (m_kValue2) m_kValue2->installEventFilter(this);
    if (m_kOperator) m_kOperator->installEventFilter(this);
    if (m_kAttributes) m_kAttributes->installEventFilter(this);

    QStringList listOps = SKGRuleObject::getListOfOperators(attType, m_updateMode ? SKGRuleObject::UPDATE : SKGRuleObject::SEARCH);
    int nb = listOps.count();
    if (iModeUpdate && attribute == "t_REALCATEGORY" && nb > 1) nb = 1;  // TODO(Stephane MANKOWSKI): unblock t_REALCATEGORY
    for (int i = 0; i < nb; ++i) {
        QString op = listOps.at(i);
        QString nlsOp = SKGRuleObject::getDisplayForOperator(op,
                        i18nc("Default value", "..."),
                        i18nc("Default value", "..."),
                        i18nc("Noun, an item's attribute", "attribute"));

        m_kOperator->addItem(nlsOp, op);
    }

    connect(m_kOperator, SIGNAL(currentIndexChanged(int)), this, SLOT(onOperatorChanged()));
    onOperatorChanged();
}

SKGPredicatCreator::~SKGPredicatCreator()
{
    m_kOperator = NULL;
    m_kValue1 = NULL;
    m_kValue2 = NULL;
    m_kAttributes = NULL;
}

bool SKGPredicatCreator::eventFilter(QObject* iObject, QEvent* iEvent)
{
    Q_UNUSED(iObject);
    if (iEvent && (iEvent->type() == QEvent::FocusIn || iEvent->type() == QEvent::FocusOut)) {
        QObject* appliFocus = QApplication::focusWidget();

        while (appliFocus) {
            if (appliFocus == this) break;
            appliFocus = appliFocus->parent();
        }
        if (!appliFocus) Q_EMIT editingFinished();
    }
    return false;
}

void SKGPredicatCreator::onOperatorChanged()
{
    QString req;
    if (m_kOperator) req = m_kOperator->itemData(m_kOperator->currentIndex()).toString();
    if (m_kValue1) m_kValue1->setVisible(req.contains("#V1S#") || req.contains("#V1#"));
    if (m_kValue2) m_kValue2->setVisible(req.contains("#V2S#") || req.contains("#V2#") || req.contains("#DF#"));
    if (m_kAttributes) m_kAttributes->setVisible(req.contains("#ATT2#"));
}

QString SKGPredicatCreator::text()
{
    return SKGPredicatCreator::getTextFromXml(xmlDescription());
}

QString SKGPredicatCreator::getTextFromXml(const QString& iXML)
{
    QDomDocument doc("SKGML");
    doc.setContent(iXML);
    QDomElement root = doc.documentElement();
    QString output = SKGRuleObject::getDisplayForOperator(root.attribute("operator"),
                     root.attribute("value"),
                     root.attribute("value2"),
                     root.attribute("att2s"));
    return output;
}

QString SKGPredicatCreator::xmlDescription()
{
    QString output;
    if (m_kOperator) {
        QString op = m_kOperator->itemData(m_kOperator->currentIndex()).toString();
        if (!op.isEmpty()) {
            QDomDocument doc("SKGML");
            QDomElement root = doc.createElement("element");
            doc.appendChild(root);

            // Condition
            root.setAttribute("operator", op);
            if (m_kValue1 && m_kValue1->isVisible()) {
                SKGDateEdit* cmbVal1 = qobject_cast<SKGDateEdit*> (m_kValue1);
                if (cmbVal1)  root.setAttribute("value", SKGServices::dateToSqlString(QDateTime(cmbVal1->date())));
                else {
                    SKGCalculatorEdit* cmbVal12 = qobject_cast<SKGCalculatorEdit*> (m_kValue1);
                    if (cmbVal12)  root.setAttribute("value", cmbVal12->text());
                    else {
                        QCheckBox* cmbVal13 = qobject_cast<QCheckBox*> (m_kValue1);
                        if (cmbVal13)  root.setAttribute("value", cmbVal13->checkState() == Qt::Checked ? "Y" : cmbVal13->checkState() == Qt::Unchecked ? "N" : "P");
                        else {
                            SKGComboBox* cmbVal14 = qobject_cast<SKGComboBox*> (m_kValue1);
                            if (cmbVal14) root.setAttribute("value", cmbVal14->text());
                        }
                    }
                }
            }
            if (m_kValue2 && m_kValue2->isVisible()) {
                SKGDateEdit* cmbVal2 = qobject_cast<SKGDateEdit*> (m_kValue2);
                if (cmbVal2)  root.setAttribute("value2", SKGServices::dateToSqlString(QDateTime(cmbVal2->date())));
                else {
                    SKGCalculatorEdit* cmbVal21 = qobject_cast<SKGCalculatorEdit*> (m_kValue2);
                    if (cmbVal21)  root.setAttribute("value2", cmbVal21->text());
                    else {
                        SKGComboBox* cmbVal22 = qobject_cast<SKGComboBox*> (m_kValue2);
                        if (cmbVal22)  root.setAttribute("value2", cmbVal22->text());
                    }
                }
            }

            if (m_kAttributes && m_kAttributes->isVisible()) {
                root.setAttribute("att2", m_kAttributes->itemData(m_kAttributes->currentIndex()).toString());
                root.setAttribute("att2s", m_kAttributes->text());
            }

            output = doc.toString();
        }
    }
    return output;
}

void SKGPredicatCreator::setXmlDescription(const QString& iXML)
{
    QDomDocument doc("SKGML");
    doc.setContent(iXML);
    QDomElement root = doc.documentElement();

    // Condition
    if (m_kOperator) {
        m_kOperator->setCurrentIndex(m_kOperator->findData(root.attribute("operator")));
        SKGDateEdit* cmbVal1 = qobject_cast<SKGDateEdit*> (m_kValue1);
        if (cmbVal1)  cmbVal1->setDate(SKGServices::stringToTime(root.attribute("value")).date());
        else {
            SKGCalculatorEdit* cmbVal12 = qobject_cast<SKGCalculatorEdit*> (m_kValue1);
            if (cmbVal12)  cmbVal12->setText(root.attribute("value"));
            else {
                QCheckBox* cmbVal13 = qobject_cast<QCheckBox*> (m_kValue1);
                if (cmbVal13)  cmbVal13->setCheckState(root.attribute("value") == "Y" ? Qt::Checked : root.attribute("value") == "P" ? Qt::PartiallyChecked : Qt::Unchecked);
                else {
                    SKGComboBox* cmbVal14 = qobject_cast<SKGComboBox*> (m_kValue1);
                    if (cmbVal14)  cmbVal14->setText(root.attribute("value"));
                }
            }
        }

        SKGDateEdit* cmbVal2 = qobject_cast<SKGDateEdit*> (m_kValue2);
        if (cmbVal2)  cmbVal2->setDate(SKGServices::stringToTime(root.attribute("value2")).date());
        else {
            SKGCalculatorEdit* cmbVal22 = qobject_cast<SKGCalculatorEdit*> (m_kValue2);
            if (cmbVal22)  cmbVal22->setText(root.attribute("value2"));
            else {
                SKGComboBox* cmbVal23 = qobject_cast<SKGComboBox*> (m_kValue2);
                if (cmbVal23) cmbVal23->setText(root.attribute("value2"));
            }
        }

        if (m_kAttributes) {
            m_kAttributes->setCurrentIndex(m_kAttributes->findData(root.attribute("att2")));
        }
    }
}

#include "skgpredicatcreator.moc"

