/***************************************************************************
 *   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 plugin for debug.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgdebugpluginwidget.h"

#include <QDomDocument>
#include <QScriptEngine>
#include <QJSEngine>

#include "skgmainpanel.h"
#include "skgdocument.h"
#include "skgtransactionmng.h"
#include "skgservices.h"
#include "skgtraces.h"

SKGDebugPluginWidget::SKGDebugPluginWidget(SKGDocument* iDocument)
    : SKGTabPage(iDocument)
{
    SKGTRACEINFUNC(10);
    if (!iDocument) {
        return;
    }

    ui.setupUi(this);

    // Set icons
    ui.kSQLPushButton->setIcon(QIcon::fromTheme("system-run"));
    ui.kSQLTransactionPushButton->setIcon(QIcon::fromTheme("system-run"));
    ui.kRefreshViewsAndIndexes->setIcon(QIcon::fromTheme("view-refresh"));

    // Fill combo box
    ui.kExplainCmb->addItem(QIcon::fromTheme("system-run"), i18nc("Execute an SQL query", "Execute"));
    ui.kExplainCmb->addItem(QIcon::fromTheme("help-hint"), i18nc("Explain an SQL query", "Explain"));
    ui.kExplainCmb->addItem(QIcon::fromTheme("games-hint"), i18nc("Explain the SQL query plan", "Explain query plan"));
    ui.kExplainCmb->addItem(QIcon::fromTheme("media-playback-start"), i18nc("Execute script", "Execute script [%1]", "javascript"));
    ui.kInput->setVisible(false);

    // Set level trace
    ui.kTraceLevel->setValue(SKGTraces::SKGLevelTrace);

    // Set profiling mode
    ui.kEnableProfilingChk->setCheckState(SKGTraces::SKGPerfo ? Qt::Checked : Qt::Unchecked);

    // Init debug page
    QStringList tables;
    ui.kSQLInput->addItem("SELECT * FROM sqlite_master;");
    iDocument->getDistinctValues("sqlite_master", "name", "type in ('table', 'view')", tables);
    int nb = tables.count();
    for (int i = 0; i < nb; ++i) {
        ui.kSQLInput->addItem("SELECT * FROM " % tables.at(i) % ';');
    }
    ui.kSQLInput->addItem("ANALYZE;");
    ui.kSQLInput->addItem("PRAGMA integrity_check;");
    for (int i = 0; i < nb; ++i) {
        ui.kSQLInput->addItem("PRAGMA table_info(" % tables.at(i) % ");");
        ui.kSQLInput->addItem("PRAGMA index_list(" % tables.at(i) % ");");
    }

    iDocument->getDistinctValues("sqlite_master", "name", "type='index'", tables);
    nb = tables.count();
    for (int i = 0; i < nb; ++i) {
        ui.kSQLInput->addItem("PRAGMA index_info(" % tables.at(i) % ");");
    }
}

SKGDebugPluginWidget::~SKGDebugPluginWidget()
{
    SKGTRACEINFUNC(10);
}

QString SKGDebugPluginWidget::getState()
{
    SKGTRACEINFUNC(10);
    QDomDocument doc("SKGML");
    QDomElement root = doc.createElement("parameters");
    doc.appendChild(root);

    root.setAttribute("explain", ui.kExplainCmb->currentIndex());
    root.setAttribute("enableProfiling", ui.kEnableProfilingChk->checkState() == Qt::Checked ? "Y" : "N");
    root.setAttribute("levelTraces", ui.kTraceLevel->value());
    root.setAttribute("sqlOrder", ui.kSQLInput->currentText());

    return doc.toString();
}

void SKGDebugPluginWidget::setState(const QString& iState)
{
    SKGTRACEINFUNC(10);
    QDomDocument doc("SKGML");
    doc.setContent(iState);
    QDomElement root = doc.documentElement();

    QString explain = root.attribute("explain");
    QString enableProfiling = root.attribute("enableProfiling");
    QString levelTraces = root.attribute("levelTraces");
    QString sqlOrder = root.attribute("sqlOrder");
    QString sqlResult = root.attribute("sqlResult");

    if (!explain.isEmpty()) {
        ui.kExplainCmb->setCurrentIndex(SKGServices::stringToInt(explain == "Y" ? "1" : explain));
    }
    if (!enableProfiling.isEmpty()) {
        ui.kEnableProfilingChk->setCheckState(enableProfiling == "Y" ? Qt::Checked : Qt::Unchecked);
    }
    if (!levelTraces.isEmpty()) {
        ui.kTraceLevel->setValue(SKGServices::stringToInt(levelTraces));
    }
    ui.kSQLInput->setText(sqlOrder);
    ui.kSQLResult->setPlainText(sqlResult);
}

void SKGDebugPluginWidget::onExecuteSqlOrderInTransaction()
{
    onExecuteSqlOrder(true);
}

void SKGDebugPluginWidget::onExecuteSqlOrder(bool iInTransaction)
{
    SKGTRACEINFUNC(10);
    SKGError err;
    int exp = ui.kExplainCmb->currentIndex();
    if (exp > 2) {
        // Script execution
        ui.kSQLResult->clear();
        QJSEngine myEngine;
        // skgresult.setText(skgdocument.getUniqueIdentifier())
        // skgerror=skgdocument.sendMessage("Hello")
        // skgerror=skgdocument.sendMessage("Hello")
        // skgmainpanel.closeAllOtherPages(skgmainpanel.currentPage())
        myEngine.globalObject().setProperty("skgresult", myEngine.newQObject(ui.kSQLResult));
        myEngine.globalObject().setProperty("skgdocument", myEngine.newQObject(getDocument()));
        myEngine.globalObject().setProperty("skgerror", myEngine.newQObject(&err));
        myEngine.globalObject().setProperty("skgmainpanel", myEngine.newQObject(SKGMainPanel::getMainPanel()));

        // Finally execute the scripting code.
        myEngine.evaluate(ui.kInput->toPlainText());
    } else {
        // SQL execution
        QString text = ui.kSQLInput->currentText();
        if (exp == 1) {
            text = "EXPLAIN " % text;
        } else if (exp == 2) {
            text = "EXPLAIN QUERY PLAN " % text;
        }
        QString oResult;
        double time = SKGServices::getMicroTime();
        if (iInTransaction) {
            SKGBEGINTRANSACTION(*getDocument(), i18nc("Display an SQL command from the debug plugin", "SQL command from debug plugin"), err);
            IFOKDO(err, getDocument()->dumpSelectSqliteOrder(text, oResult));
        } else {
            QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
            err = getDocument()->dumpSelectSqliteOrder(text, oResult);
            QApplication::restoreOverrideCursor();
        }
        time = SKGServices::getMicroTime() - time;

        oResult += i18nc("Display the execution time needed by an SQL query", "\nExecution time: %1 ms", SKGServices::doubleToString(time));

        IFOK(err) {
            ui.kSQLResult->setPlainText(oResult);
        } else {
            ui.kSQLResult->setPlainText(err.getFullMessageWithHistorical());
        }
    }
}

void SKGDebugPluginWidget::onTraceLevelModified()
{
    SKGTRACEINFUNC(10);
    SKGTraces::SKGLevelTrace = ui.kTraceLevel->value();
}

void SKGDebugPluginWidget::onModeChanged()
{
    SKGTRACEINFUNC(10);
    int exp = ui.kExplainCmb->currentIndex();
    ui.kInput->setVisible(exp > 2);
    ui.kSQLInput->setVisible(exp < 3);
}

void SKGDebugPluginWidget::onProfilingModeChanged()
{
    SKGTRACEINFUNC(10);
    SKGTraces::SKGPerfo = (ui.kEnableProfilingChk->checkState() == Qt::Checked);
}

void SKGDebugPluginWidget::onRefreshViewsAndIndexes()
{
    SKGTRACEINFUNC(10);
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
    SKGError err;
    err = getDocument()->refreshViewsIndexesAndTriggers();
    IFKO(err) {
        ui.kSQLResult->setPlainText(err.getFullMessageWithHistorical());
    }
    QApplication::restoreOverrideCursor();
}


