/***************************************************************************
 *   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 for bank management.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgbankplugin.h"
#include "skgbankpluginwidget.h"
#include "skgbankboardwidget.h"
#include "skgaccountboardwidget.h"
#include "skgmainpanel.h"
#include "skgaccountobject.h"
#include "skgoperationobject.h"
#include "skgsuboperationobject.h"
#include "skgtraces.h"
#include "skgdocumentbank.h"
#include "skgtransactionmng.h"
#include "skgbankobject.h"

#include <kactioncollection.h>
#include <kaboutdata.h>

/**
 * This plugin factory.
 */
K_PLUGIN_FACTORY(SKGBankPluginFactory, registerPlugin<SKGBankPlugin>();)
/**
 * This plugin export.
 */
K_EXPORT_PLUGIN(SKGBankPluginFactory("skrooge_bank", "skrooge_bank"))

SKGBankPlugin::SKGBankPlugin(QObject* iParent, const QVariantList& /*iArg*/)
    : SKGInterfacePlugin(iParent), m_currentBankDocument(NULL)
{
    SKGTRACEIN(10, "SKGBankPlugin::SKGBankPlugin");
}

SKGBankPlugin::~SKGBankPlugin()
{
    SKGTRACEIN(10, "SKGBankPlugin::~SKGBankPlugin");
    m_currentBankDocument = NULL;
    m_reconciliateAction = NULL;
}

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

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

    //Menu
    m_reconciliateAction = new KAction(KIcon("skrooge_duplicate"), i18nc("Verb: Reconciliation is process through which you ensure compliance with your bank's statement", "Reconcile..."), this);
    connect(m_reconciliateAction, SIGNAL(triggered(bool)), this, SLOT(actionReconciliate()));
    actionCollection()->addAction(QLatin1String("edit_reconciliate"), m_reconciliateAction);
    m_reconciliateAction->setShortcut(Qt::ALT + Qt::Key_R);

    if (SKGMainPanel::getMainPanel()) SKGMainPanel::getMainPanel()->registerGlobalAction("edit_reconciliate", m_reconciliateAction);
    return true;
}

int SKGBankPlugin::getNbDashboardWidgets()
{
    return 2;
}

QString SKGBankPlugin::getDashboardWidgetTitle(int iIndex)
{
    if (iIndex == 0) return i18nc("Noun, a list of bank accounts", "Accounts");
    else if (iIndex == 1) return i18nc("Noun, a list of banks", "Banks");
    return "";
}

SKGWidget* SKGBankPlugin::getDashboardWidget(int iIndex)
{
    if (iIndex == 0) return new SKGAccountBoardWidget(m_currentBankDocument);
    else if (iIndex == 1) return new SKGBankBoardWidget(m_currentBankDocument);
    return NULL;
}

SKGTabPage* SKGBankPlugin::getWidget()
{
    SKGTRACEIN(10, "SKGBankPlugin::getWidget");
    return new SKGBankPluginWidget(m_currentBankDocument);
}

QString SKGBankPlugin::title() const
{
    return i18nc("Display a list of Accounts", "Accounts");
}

QString SKGBankPlugin::icon() const
{
    return "view-bank-account";
}

QString SKGBankPlugin::toolTip() const
{
    return i18nc("This allows the user to manage his list of accounts", "Manage your accounts");
}

QStringList SKGBankPlugin::tips() const
{
    QStringList output;
    output.push_back(i18nc("Description of a tip", "<p>... you can associate a logo with your banks.</p>"));
    output.push_back(i18nc("Description of a tip", "<p>... accounts can be merged by drag & drop.</p>"));
    return output;
}

int SKGBankPlugin::getOrder() const
{
    //Must be one of the first
    return 10;
}

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

void SKGBankPlugin::refresh()
{
    SKGTRACEIN(10, "SKGBankPlugin::refresh");
    if (m_currentBankDocument && SKGMainPanel::getMainPanel()) {
        SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();
        if (selection.count() > 0) {
            bool onAccount = (selection.at(0).getRealTable() == "account");
            if (m_reconciliateAction) m_reconciliateAction->setEnabled(onAccount);
        } else {
            if (m_reconciliateAction) m_reconciliateAction->setEnabled(false);
        }
    }
}

void SKGBankPlugin::actionReconciliate()
{
    if (m_currentBankDocument && SKGMainPanel::getMainPanel()) {
        //Open in operation plugin
        SKGObjectBase::SKGListSKGObjectBase selection = SKGMainPanel::getMainPanel()->getSelectedObjects();
        int nb = selection.count();
        for (int i = 0; i < nb; ++i) {
            SKGAccountObject accountObj = selection[i];

            QDomDocument doc("SKGML");
            doc.setContent(m_currentBankDocument->getParameter("SKGOPERATION_DEFAULT_PARAMETERS"));
            QDomElement root = doc.documentElement();
            if (root.isNull()) {
                root = doc.createElement("parameters");
                doc.appendChild(root);
            }

            root.setAttribute("account", accountObj.getName());
            root.setAttribute("modeInfoZone", "1");
            root.setAttribute("currentPage", "-1");
            SKGMainPanel::getMainPanel()->openPage(SKGMainPanel::getMainPanel()->getPluginByName("Skrooge operation plugin"), -1, doc.toString());
        }
    }
}

SKGAdviceList SKGBankPlugin::advices() const
{
    SKGTRACEIN(10, "SKGBankPlugin::advices");
    SKGAdviceList output;

    //Get bank without accounts
    SKGStringListList result;
    m_currentBankDocument->executeSelectSqliteOrder("SELECT bank.t_name FROM bank WHERE NOT EXISTS (SELECT 1 FROM account WHERE account.rd_bank_id=bank.id)", result);
    int nb = result.count();
    for (int i = 1; i < nb; ++i) { //Ignore header
        //Get parameters
        QStringList line = result.at(i);
        QString bank = line.at(0);

        SKGAdvice ad;
        ad.setUUID("skgbankplugin_withoutaccount|" % bank);
        ad.setPriority(3);
        ad.setShortMessage(i18nc("A bank is in the list of used banks, but it doesn't have any account attached", "Bank '%1' has no account", bank));
        ad.setLongMessage(i18nc("User can delete banks with no accounts", "Don't forget to remove useless banks"));
        QStringList autoCorrections;
        autoCorrections.push_back(i18nc("Action to delete a bank", "Delete '%1'", bank));
        ad.setAutoCorrections(autoCorrections);
        output.push_back(ad);
    }

    //Get accounts closed with money
    m_currentBankDocument->executeSelectSqliteOrder("SELECT t_name FROM v_account WHERE f_CURRENTAMOUNT>0.1 AND t_close='Y'", result);
    nb = result.count();
    for (int i = 1; i < nb; ++i) { //Ignore header
        //Get parameters
        QStringList line = result.at(i);
        QString account = line.at(0);

        SKGAdvice ad;
        ad.setUUID("skgbankplugin_closedaccount|" % account);
        ad.setPriority(3);
        ad.setShortMessage(i18nc("A account is closed but the amount is not equal to 0", "Closed account '%1' still has money", account));
        ad.setLongMessage(i18nc("Advice on making the best (long)", "This is may be not normal"));
        QStringList autoCorrections;
        autoCorrections.push_back(i18nc("Action to reopen the account", "Reopen '%1'", account));
        autoCorrections.push_back(i18nc("Action to create a fake operation to set the amount of the account to 0", "Create fake operation"));
        ad.setAutoCorrections(autoCorrections);
        output.push_back(ad);
    }

    return output;
}

SKGError SKGBankPlugin::executeAdviceCorrection(const QString& iAdviceIdentifier, int iSolution) const
{
    if (m_currentBankDocument && iAdviceIdentifier.startsWith(QLatin1String("skgbankplugin_withoutaccount|"))) {
        //Get parameters
        QString bank = iAdviceIdentifier.right(iAdviceIdentifier.length() - 29);

        SKGError err;
        {
            SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Delete banks with no account", "Delete unused banks")  , err);

            SKGBankObject bankObj(m_currentBankDocument);
            err = bankObj.setName(bank);
            if (!err) err = bankObj.load();
            if (!err) err = bankObj.remove();
        }

        //status bar
        if (!err) err = SKGError(0, i18nc("Successfully deleted a bank with no account", "Unused bank deleted"));
        else err.addError(ERR_FAIL, i18nc("Could not delete a bank with no account", "Unused bank deletion failed"));

        //Display error
        SKGMainPanel::displayErrorMessage(err);

        return SKGError();
    } else if (m_currentBankDocument && iAdviceIdentifier.startsWith(QLatin1String("skgbankplugin_closedaccount|"))) {
        //Get parameters
        QString account = iAdviceIdentifier.right(iAdviceIdentifier.length() - 28);

        SKGAccountObject accountObj(m_currentBankDocument);
        SKGError err = accountObj.setName(account);
        if (!err) err = accountObj.load();

        if (iSolution == 0) {
            {
                SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Reopen a closed account", "Reopen account '%1'", account)  , err);
                if (!err) err = accountObj.setClosed(false);
                if (!err) err = accountObj.save();
            }

            //status bar
            if (!err) err = SKGError(0, i18nc("Successfully reopen account", "Account reopened"));
            else err.addError(ERR_FAIL, i18nc("Failure", "reopening of the account failed"));
        } else if (iSolution == 1) {
            {
                SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Create fake operation"), err);

                SKGOperationObject op;
                if (!err) err = accountObj.setClosed(false);
                if (!err) err = accountObj.addOperation(op);
                if (!err) err = op.setDate(QDate::currentDate());
                if (!err) err = op.setComment(i18nc("Noun, default comment for a fake operation", "Fake operation"));
                SKGUnitObject unit;
                if (!err) err = accountObj.getUnit(unit);
                if (!err) err = op.setUnit(unit);
                if (!err) err = op.save();

                SKGSubOperationObject sop;
                if (!err) err = op.addSubOperation(sop);
                if (!err) err = sop.setQuantity(-accountObj.getAmount(QDate::currentDate()));
                if (!err) err = sop.save();
            }

            //status bar
            if (!err) err = SKGError(0, i18nc("Successful message after an user action", "Fake operation created."));
            else err.addError(ERR_FAIL, i18nc("Error message",  "Creation failed"));
        }

        //Display error
        SKGMainPanel::displayErrorMessage(err);

        return SKGError();
    }
    return SKGInterfacePlugin::executeAdviceCorrection(iAdviceIdentifier, iSolution);
}

#include "skgbankplugin.moc"
