/***************************************************************************
 *   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 Skrooge plugin to generate report.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgreportplugin.h"

#include <KAction>
#include <KActionCollection>
#include <KAboutData>
#include <KGenericFactory>

#include <QDomDocument>

#include "skgreportpluginwidget.h"
#include "skgtraces.h"
#include "skgmainpanel.h"
#include "skgservices.h"
#include "skgaccountobject.h"
#include "skgcategoryobject.h"
#include "skgtrackerobject.h"
#include "skgunitobject.h"
#include "skgruleobject.h"
#include "skgpayeeobject.h"
#include "skgnodeobject.h"
#include "skgreportboardwidget.h"
#include "skgdocumentbank.h"
#include "skgreport_settings.h"

/**
 * This plugin factory.
 */
K_PLUGIN_FACTORY(SKGReportPluginFactory, registerPlugin<SKGReportPlugin>();)
/**
 * This plugin export.
 */
K_EXPORT_PLUGIN(SKGReportPluginFactory("skrooge_report", "skrooge_report"))

SKGReportPlugin::SKGReportPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& /*iArg*/) :
    SKGInterfacePlugin(iParent),
    m_openReportAction(NULL), m_currentBankDocument(NULL)
{
    Q_UNUSED(iWidget);
    SKGTRACEINFUNC(10);
}

SKGReportPlugin::~SKGReportPlugin()
{
    SKGTRACEINFUNC(10);
    m_currentBankDocument = NULL;
    m_openReportAction = NULL;
}

bool SKGReportPlugin::setupActions(SKGDocument* iDocument, const QStringList& iArgument)
{
    SKGTRACEINFUNC(10);
    Q_UNUSED(iArgument);
    m_currentBankDocument = qobject_cast<SKGDocumentBank*>(iDocument);
    if (m_currentBankDocument == NULL) {
        return false;
    }

    setComponentData(KGlobal::mainComponent());
    setXMLFile("../skrooge_report/skrooge_report.rc");

    // Menu
    QStringList overlayopen;
    overlayopen.push_back("skg_open");
    m_openReportAction = new KAction(KIcon("view-investment", NULL, overlayopen), i18nc("Verb", "Open report..."), this);
    connect(m_openReportAction, SIGNAL(triggered(bool)), this, SLOT(onOpenReport()));
    m_openReportAction->setShortcut(Qt::META + Qt::Key_R);
    registerGlobalAction("open_report", m_openReportAction);

    // ---------------
    KAction* act = new KAction(KIcon("security-low", NULL, overlayopen), i18nc("Verb", "Open very old operations..."), this);
    act->setData(QString("skg://skrooge_operation_plugin/?title_icon=security-low&title=" %
                         SKGServices::encodeForUrl(i18nc("Noun, a list of items", "Very old operations")) %
                         "&operationWhereClause=" % SKGServices::encodeForUrl("d_date<=(SELECT date('now', '-50 year')) AND d_date<>'0000-00-00'")));
    connect(act, SIGNAL(triggered(bool)), SKGMainPanel::getMainPanel(), SLOT(openPage()));
    registerGlobalAction("view_open_very_old_operations", act);
    return true;
}

void SKGReportPlugin::refresh()
{
    SKGTRACEINFUNC(10);
    if (SKGMainPanel::getMainPanel()) {
        SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();

        if (selection.count() > 0) {
            QString table = selection.at(0).getRealTable();
            bool onOperation = (table == "operation" || table == "suboperation" || table == "account" || table == "unit" || table == "category" || table == "refund" || table == "payee" || table == "rule");
            if (m_openReportAction) {
                m_openReportAction->setEnabled(onOperation);
            }
        } else {
            if (m_openReportAction) {
                m_openReportAction->setEnabled(false);
            }
        }
    }
}

int SKGReportPlugin::getNbDashboardWidgets()
{
    return 1;
}

QString SKGReportPlugin::getDashboardWidgetTitle(int iIndex)
{
    Q_UNUSED(iIndex);
    return i18nc("Noun, the title of a section", "Report");
}

SKGBoardWidget* SKGReportPlugin::getDashboardWidget(int iIndex)
{
    Q_UNUSED(iIndex);
    return new SKGReportBoardWidget(m_currentBankDocument);
}

SKGTabPage* SKGReportPlugin::getWidget()
{
    SKGTRACEINFUNC(10);
    return new SKGReportPluginWidget(m_currentBankDocument);
}

QWidget* SKGReportPlugin::getPreferenceWidget()
{
    SKGTRACEINFUNC(10);
    QWidget* w = new QWidget();
    ui.setupUi(w);
    return w;
}

KConfigSkeleton* SKGReportPlugin::getPreferenceSkeleton()
{
    return skgreport_settings::self();
}

QString SKGReportPlugin::title() const
{
    return i18nc("Noun", "Report");
}

QString SKGReportPlugin::icon() const
{
    return "view-investment";
}

QString SKGReportPlugin::toolTip() const
{
    return i18nc("Noun", "Generate report");
}

int SKGReportPlugin::getOrder() const
{
    return 40;
}

QStringList SKGReportPlugin::tips() const
{
    QStringList output;
    output.push_back(i18nc("Description of a tips", "<p>... you can double click on a value in '%1' to show corresponding operations.</p>", title()));
    output.push_back(i18nc("Description of a tips", "<p>... you can open reports for selections made in other pages.</p>"));
    output.push_back(i18nc("Description of a tips", "<p>... you can export reports in many formats.</p>"));
    return output;
}

bool SKGReportPlugin::isInPagesChooser() const
{
    return true;
}

void SKGReportPlugin::getTitleAndWhereClause(const SKGObjectBase::SKGListSKGObjectBase& iSelection, QString& oTitle, QString& oWhereClause) const
{
    int nb = iSelection.count();
    if (nb > 0) {
        QString table = iSelection.at(0).getRealTable();
        if (table == "account") {
            oWhereClause = "rd_account_id in (";
            oTitle = i18nc("Noun, a list of items", "Operations of account ");

            for (int i = 0; i < nb; ++i) {
                SKGAccountObject tmp(iSelection.at(i));
                if (i) {
                    oWhereClause += ',';
                    oTitle += ',';
                }
                oWhereClause += SKGServices::intToString(tmp.getID());
                oTitle += i18n("'%1'", tmp.getName());
            }
            oWhereClause += ')';
        } else if (table == "unit") {
            oWhereClause = "rc_unit_id in (";
            oTitle = i18nc("Noun, a list of items", "Operations with Unit equal to ");

            for (int i = 0; i < nb; ++i) {
                SKGUnitObject tmp(iSelection.at(i));
                if (i) {
                    oWhereClause += ',';
                    oTitle += ',';
                }
                oWhereClause += SKGServices::intToString(tmp.getID());
                oTitle += i18n("'%1'", tmp.getName());
            }
            oWhereClause += ')';
        } else if (table == "category") {
            oWhereClause = "t_REALCATEGORY in (";
            QString wc2;
            oTitle = i18nc("Noun, a list of items", "Operations with Category equal to ");

            for (int i = 0; i < nb; ++i) {
                SKGCategoryObject tmp(iSelection.at(i));
                if (i) {
                    oWhereClause += ',';
                    wc2 += " OR ";
                    oTitle += ',';
                }
                oWhereClause += '\'' % SKGServices::stringToSqlString(tmp.getFullName()) % '\'';
                wc2 += "t_REALCATEGORY like '" % SKGServices::stringToSqlString(tmp.getFullName()) % "%'";
                oTitle += i18n("'%1'", tmp.getFullName());
            }
            oWhereClause += ") OR " % wc2;
        } else if (table == "refund") {
            oWhereClause = "r_refund_id in (";
            oTitle = i18nc("Noun, a list of items", "Operations followed by ");

            for (int i = 0; i < nb; ++i) {
                SKGTrackerObject tmp(iSelection.at(i));
                if (i) {
                    oWhereClause += ',';
                    oTitle += ',';
                }
                oWhereClause += SKGServices::intToString(tmp.getID());
                oTitle += i18n("'%1'", tmp.getName());
            }
            oWhereClause += ')';
        } else if (table == "payee") {
            oWhereClause = "r_payee_id in (";
            oTitle = i18nc("Noun, a list of items", "Operations assigned to ");

            for (int i = 0; i < nb; ++i) {
                SKGPayeeObject tmp(iSelection.at(i));
                if (i) {
                    oWhereClause += ',';
                    oTitle += ',';
                }
                oWhereClause += SKGServices::intToString(tmp.getID());
                oTitle += i18n("'%1'", tmp.getName());
            }
            oWhereClause += ')';
        } else if (table == "operation") {
            oWhereClause = "i_OPID in (";
            oTitle = i18nc("Noun, a list of items", "Selected operations");

            for (int i = 0; i < nb; ++i) {
                if (i) {
                    oWhereClause += ',';
                }
                oWhereClause += SKGServices::intToString(iSelection.at(i).getID());
            }
            oWhereClause += ')';
        } else if (table == "suboperation") {
            oWhereClause = "i_SUBOPID in (";
            oTitle = i18nc("Noun, a list of items", "Selected sub operations");

            for (int i = 0; i < nb; ++i) {
                if (i) {
                    oWhereClause += ',';
                }
                oWhereClause += SKGServices::intToString(iSelection.at(i).getID());
            }
            oWhereClause += ')';
        } else if (table == "rule") {
            oTitle = i18nc("Noun, a list of items", "Operations corresponding to rule ");

            for (int i = 0; i < nb; ++i) {
                SKGRuleObject tmp(iSelection.at(i));
                QString ruleWc = tmp.getSelectSqlOrder();
                if (!ruleWc.isEmpty()) {
                    if (!oWhereClause.isEmpty()) {
                        oWhereClause += " OR ";
                        oTitle += ',';
                    }
                    oWhereClause += '(' % ruleWc % ')';
                    oTitle += i18n("'%1'", tmp.getSearchDescription());
                }
            }
        }
    }
}


void SKGReportPlugin::onOpenReport()
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);
    if (SKGMainPanel::getMainPanel()) {
        SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();

        int nb = selection.count();
        if (nb > 0) {
            QString titleTable;
            QString wc;
            getTitleAndWhereClause(selection, titleTable, wc);

            // Call report plugin
            SKGMainPanel::getMainPanel()->openPage("skg://skrooge_report_plugin/?period=0&title_icon=" % icon() % "&title=" % SKGServices::encodeForUrl(titleTable) % "&operationWhereClause=" % SKGServices::encodeForUrl(wc));
        }
    }
}

SKGAdviceList SKGReportPlugin::advice(const QStringList& iIgnoredAdvice)
{
    SKGTRACEINFUNC(10);
    SKGAdviceList output;

    // Very old operation
    if (!iIgnoredAdvice.contains("skgreportplugin_veryold")) {
        bool exist = false;
        m_currentBankDocument->existObjects("operation", "d_date<=(SELECT date('now', '-50 year')) AND d_date<>'0000-00-00'", exist);
        if (exist) {
            SKGAdvice ad;
            ad.setUUID("skgreportplugin_veryold");
            ad.setPriority(3);
            ad.setShortMessage(i18nc("Advice on making the best (short)", "Some operations are very old"));
            ad.setLongMessage(i18nc("Advice on making the best (long)", "For performances reasons, very old operations are not taken into account in graph report. Check if these operations are normal."));
            QStringList autoCorrections;
            autoCorrections.push_back("skg://view_open_very_old_operations");
            ad.setAutoCorrections(autoCorrections);
            output.push_back(ad);
        }
    }
    return output;
}

#include "skgreportplugin.moc"
