/***************************************************************************
 *   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 "skgquerycreator.h"

#include <QDomDocument>
#include <QHeaderView>

#include "skgquerydelegate.h"
#include "skgservices.h"
#include "skgdocument.h"
#include "skgpredicatcreator.h"
#include "skgruleobject.h"

SKGQueryCreator::SKGQueryCreator(QWidget* iParent)
    : QWidget(iParent), m_document(NULL), m_updateMode(false)
{
    ui.setupUi(this);

    ui.kList->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
    ui.kList->verticalHeader()->setResizeMode(QHeaderView::Fixed);
    ui.kList->setWordWrap(false);
    ui.kList->horizontalHeader()->setMovable(true);

    connect(ui.kList, SIGNAL(removeLine(int)), this, SLOT(removeLine(int)));


    addNewLine();
}

SKGQueryCreator::~SKGQueryCreator()
{
    m_document = NULL;
}

void SKGQueryCreator::setParameters(SKGDocument* iDocument, const QString& iTable, const QStringList& iListAttribute, bool iModeUpdate)
{
    m_document = iDocument;
    m_table = iTable;
    m_updateMode = iModeUpdate;

//     QString txt=(updateMode ? i18nc("Description", "Double click on a field name to add it to your modification definition.") : i18nc("Description", "Double click on a field name to add it to your search definition."))+'\n'+i18nc("Description", "Double click on a cell to modify it.");
//     ui.kLabel->setComment ( "<html><body><b>"+SKGServices::stringToHtml ( txt ) +"</b></body></html>" );
//     ui.kLabel->setPixmap ( KIcon ( updateMode ? "view-refresh" :"edit-find" ).pixmap ( 22, 22 ), KTitleWidget::ImageLeft );

    // Build list of attributes
    if (m_document) {
        SKGQueryDelegate* delegate = new SKGQueryDelegate(ui.kList, m_document, m_updateMode, iListAttribute);
        connect(delegate, SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), this, SLOT(onCloseEditor()));

        ui.kList->setItemDelegate(delegate);

        // Keep only existing attribute
        SKGServices::SKGAttributesList listAtts;
        SKGServices::SKGAttributesList attributes;
        m_document->getAttributesDescription(m_table, attributes);
        foreach(const SKGServices::SKGAttributeInfo & att, attributes) {
            if (iListAttribute.count() == 0 || iListAttribute.contains(att.name)) listAtts.push_back(att);
        }

        // Adding properties
        int nb = iListAttribute.count();
        for (int i = 0; i < nb; ++i) {
            QString att = iListAttribute.at(i);
            if (att.startsWith(QLatin1String("p_"))) {
                SKGServices::SKGAttributeInfo info;
                info.name = att;
                info.display = att.right(att.length() - 2);
                info.type = SKGServices::TEXT;
                info.icon = iDocument->getIcon(att);
                listAtts.push_back(info);
            }
        }

        ui.kList->setRowCount(0);

        int nbCol = listAtts.count();
        for (int i = 0; i < nbCol; ++i) {
            QListWidgetItem* listItem = new QListWidgetItem(listAtts.at(i).icon, listAtts.at(i).display);
            ui.kListAtt->addItem(listItem);
            listItem->setData(Qt::UserRole, listAtts.at(i).name);
        }
        ui.kListAtt->sortItems();
        ui.kListAtt->setModelColumn(nbCol);
        connect(ui.kList->verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(removeLine(int)));
        connect(ui.kList->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(removeColumn(int)));

        addNewLine();
    }
}

int SKGQueryCreator::getIndexQueryColumn(const QString& iAttribute , int row)
{
    // Search column for this attribute
    int output = -1;
    int nbCol = ui.kList->columnCount();
    for (int i = 0; i < nbCol && output == -1; ++i) {
        QTableWidgetItem* it_h = ui.kList->horizontalHeaderItem(i);
        if (it_h && iAttribute == it_h->data(Qt::UserRole).toString()) {
            if (row >= 0) {
                // Check if the cell is empty
                QTableWidgetItem* it = ui.kList->item(row, i);
                if (it) {
                    if (it->text().isEmpty()) {
                        output = i;
                    }
                }
            } else {
                output = i;
            }
        }
    }

    // If not existing, we have to create it
    if (output == -1) {
        int nb = ui.kListAtt->count();
        for (int i = 0; i < nb; ++i) {
            QListWidgetItem* it = ui.kListAtt->item(i);
            if (it && iAttribute == it->data(Qt::UserRole).toString()) {
                addColumnFromAttribut(it);
                output = nbCol;
                break;
            }
        }
    }

    return output;
}

void SKGQueryCreator::clearContents()
{
    ui.kList->clearContents();
    ui.kList->setRowCount(0);

    addNewLine();
}

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

    ui.kList->clearContents();
    ui.kList->setRowCount(0);
    ui.kList->setColumnCount(0);

    int row = -1;
    QDomNode l = root.firstChild();
    while (!l.isNull()) {
        QDomElement elementl = l.toElement();
        if (!elementl.isNull()) {
            // Add new line
            addNewLine();
            ++row;

            QDomNode n = elementl.firstChild();
            while (!n.isNull()) {
                QDomElement element = n.toElement();
                if (!element.isNull()) {
                    QString attribute = element.attribute("attribute");
                    int idx = getIndexQueryColumn(attribute, row);
                    if (idx >= 0) {
                        QDomDocument doc2("SKGML");
                        QDomElement root2 = doc2.createElement("element");
                        doc2.appendChild(root2);
                        root2.setAttribute("operator", element.attribute("operator"));
                        root2.setAttribute("value", element.attribute("value"));
                        root2.setAttribute("value2", element.attribute("value2"));
                        root2.setAttribute("att2", element.attribute("att2"));
                        root2.setAttribute("att2s", element.attribute("att2s"));
                        QTableWidgetItem* it = ui.kList->item(row, idx);
                        if (it) {
                            QString xml = doc2.toString();

                            it->setText(SKGPredicatCreator::getTextFromXml(xml));
                            it->setData(Qt::UserRole, xml);
                        }
                    }
                }
                n = n.nextSibling();
            }
        }
        l = l.nextSibling();
    }

    addNewLine();
}

QString SKGQueryCreator::getXMLCondition()
{
    QString output;
    QHeaderView* hHeader = ui.kList->horizontalHeader();
    if (hHeader) {
        QDomDocument doc("SKGML");
        QDomElement element = doc.createElement("element");
        doc.appendChild(element);

        element.appendChild(doc.createComment("OR"));

        bool empty = true;
        int nbRow = ui.kList->rowCount();
        int nbCol = hHeader->count();
        for (int j = 0; j < nbRow; ++j) {
            QDomElement elementLine = doc.createElement("element");
            element.appendChild(elementLine);

            elementLine.appendChild(doc.createComment("AND"));

            bool atLeastOne = false;
            for (int i = 0; i < nbCol; ++i) {
                int iRealPos = hHeader->logicalIndex(i);
                QTableWidgetItem* it = ui.kList->item(j, iRealPos);
                if (it) {
                    QString co = it->data(Qt::UserRole).toString();
                    if (!co.isEmpty()) {
                        QDomElement elementElement = doc.createElement("element");
                        elementLine.appendChild(elementElement);

                        QTableWidgetItem* it_h = ui.kList->horizontalHeaderItem(iRealPos);
                        QString attname = it_h->data(Qt::UserRole).toString();

                        QDomDocument doc2("SKGML");
                        doc2.setContent(co);
                        QDomElement root2 = doc2.documentElement();

                        elementElement.setAttribute("attribute", attname);
                        elementElement.setAttribute("operator", root2.attribute("operator"));
                        if (root2.hasAttribute("value")) elementElement.setAttribute("value", root2.attribute("value"));
                        if (root2.hasAttribute("value2")) elementElement.setAttribute("value2", root2.attribute("value2"));
                        if (root2.hasAttribute("att2")) elementElement.setAttribute("att2", root2.attribute("att2"));
                        if (root2.hasAttribute("att2s")) elementElement.setAttribute("att2s", root2.attribute("att2s"));

                        atLeastOne = true;
                        empty = false;
                    }
                }
            }

            if (!atLeastOne) element.removeChild(elementLine);
        }
        if (!empty) output = doc.toString();
    }

    return output;
}

void SKGQueryCreator::onCloseEditor()
{
    // If all lignes have at least one value then add a new line
    bool lineEmpty = false;
    int nbCol = ui.kList->columnCount();
    int nbRow = ui.kList->rowCount();
    for (int j = 0; !lineEmpty && j < nbRow; ++j) {
        lineEmpty = true;
        for (int i = 0; lineEmpty && i < nbCol; ++i) {
            QTableWidgetItem* it = ui.kList->item(j, i);
            if (it && !it->text().isEmpty()) lineEmpty = false;
        }
    }

    if (!lineEmpty) addNewLine();
}

void SKGQueryCreator::onAddColumn()
{
    QList<QListWidgetItem*> selection = ui.kListAtt->selectedItems();
    if (selection.count() == 1) {
        QListWidgetItem* listItem = selection.at(0);
        addColumnFromAttribut(listItem);
    }
}

void SKGQueryCreator::addColumnFromAttribut(const QListWidgetItem* listItem)
{
    if (listItem) {
        bool previous = ui.kList->blockSignals(true);

        int nb = ui.kList->columnCount();
        ui.kList->setColumnCount(nb + 1);

        // Create header
        QTableWidgetItem* item = new QTableWidgetItem(listItem->icon() , listItem->text());
        item->setData(Qt::UserRole, listItem->data(Qt::UserRole));
        ui.kList->setHorizontalHeaderItem(nb, item);

        // Create items
        int nbRows = ui.kList->rowCount();
        for (int i = 0; i < nbRows; ++i) {
            ui.kList->setItem(i, nb, new QTableWidgetItem());
        }
        ui.kList->blockSignals(previous);
    }
}

void SKGQueryCreator::addNewLine()
{
    // add line is only for
    if (!m_updateMode || ui.kList->rowCount() < 1) {
        bool previous = ui.kList->blockSignals(true);

        int nbCol = ui.kList->columnCount();
        int row = ui.kList->rowCount();
        ui.kList->insertRow(row);

        // Add a delete icon
        if (!m_updateMode) {
            ui.kList->setVerticalHeaderItem(row, new QTableWidgetItem(KIcon("edit-delete"), ""));
        }

        for (int i = 0; i < nbCol; ++i) {
            QTableWidgetItem* item = new QTableWidgetItem();
            ui.kList->setItem(row, i, item);
        }
        ui.kList->blockSignals(previous);

        ui.kList->resizeColumnsToContents();
    }
}

int SKGQueryCreator::getColumnsCount()
{
    return ui.kList->horizontalHeader()->count();
}

int SKGQueryCreator::getLinesCount()
{
    return ui.kList->rowCount();
}

void SKGQueryCreator::removeColumn(int iColumn)
{
    ui.kList->removeColumn(iColumn);

    // To be sure that we have at least an empty line
    onCloseEditor();
}

void SKGQueryCreator::removeLine(int iRow)
{
    ui.kList->removeRow(iRow);

    // To be sure that we have at least an empty line
    onCloseEditor();
}

#include "skgquerycreator.moc"

