/***************************************************************************
 *   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
 * A plugin for monthly report.
 *
 * @author Stephane MANKOWSKI
 */
#include "skgmonthlypluginwidget.h"
#include "skgmainpanel.h"
#include "skgtraces.h"
#include "skgreport.h"
#include "skgtransactionmng.h"

#include <kstandarddirs.h>
#include <knewstuff3/downloaddialog.h>
#include <knewstuff3/uploaddialog.h>
#include <kio/netaccess.h>
#include <kmenu.h>
#include <kzip.h>
#include <kcomponentdata.h>
#include <kaboutdata.h>

#include <QDomDocument>
#include <QPrinter>
#include <QPrintDialog>
#include <QTextStream>
#include <QFile>
#include <QDir>
#include <QDesktopServices>
#include <QWebFrame>

SKGMonthlyPluginWidget::SKGMonthlyPluginWidget(SKGDocument* iDocument)
    : SKGTabPage(iDocument)
{
    SKGTRACEIN(1, "SKGMonthlyPluginWidget::SKGMonthlyPluginWidget");
    if (!iDocument) return;

    ui.setupUi(this);
    ui.kDeleteTemplate->hide();

    //Make needed paths
    QString path = KStandardDirs::locateLocal("data", KGlobal::mainComponent().aboutData()->appName() % "/html/default/");

    //Copy "default" directory in locale
    foreach(const QString & file, KStandardDirs().findAllResources("data", KGlobal::mainComponent().aboutData()->appName() % "/html/default/*.html")) {
        QFile(file).copy(path % QFileInfo(file).fileName());
    }

    ui.kRefresh->setIcon(KIcon("view-refresh"));
    ui.kGetNewHotStuff->setIcon(KIcon("get-hot-new-stuff"));
    ui.kDeleteTemplate->setIcon(KIcon("edit-delete"));

    connect((const QObject*) getDocument(), SIGNAL(tableModified(QString,int)), this, SLOT(dataModified(QString,int)), Qt::QueuedConnection);

    QStringList overlays;
    overlays.push_back("list-add");
    m_upload = new KAction(KIcon("get-hot-new-stuff", NULL, overlays), i18n("Upload"), this);
    connect(m_upload, SIGNAL(triggered(Qt::MouseButtons,Qt::KeyboardModifiers)), SLOT(onPutNewHotStuff()));
    connect(ui.kWebView, SIGNAL(linkClicked(QUrl)), this, SLOT(onOpen(QUrl)));

    KMenu* menu = new KMenu();
    menu->addAction(m_upload);
    ui.kGetNewHotStuff->setMenu(menu);

    //Refresh
    fillTemplateList();
    dataModified("", 0);
}

SKGMonthlyPluginWidget::~SKGMonthlyPluginWidget()
{
    SKGTRACEIN(1, "SKGMonthlyPluginWidget::~SKGMonthlyPluginWidget");
}

QString SKGMonthlyPluginWidget::getState()
{
    SKGTRACEIN(10, "SKGMonthlyPluginWidget::getState");
    QDomDocument doc("SKGML");
    QDomElement root = doc.createElement("parameters");
    doc.appendChild(root);

    //Get state
    root.setAttribute("month", ui.kMonth->text());
    root.setAttribute("template", ui.kTemplate->text());
    root.setAttribute("web", ui.kWebView->getState());

    return doc.toString();
}

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

    //Set state
    QString month = root.attribute("month");
    if (!month.isEmpty()) ui.kMonth->setText(month);

    QString webS = root.attribute("web");
    if (!webS.isEmpty()) ui.kWebView->setState(webS);

    QString templat = root.attribute("template");
    if (!templat.isEmpty()) {
        bool p = ui.kTemplate->blockSignals(true);
        ui.kTemplate->setText(templat);
        ui.kTemplate->blockSignals(p);
        onTemplateChanged();
    }
}

QString SKGMonthlyPluginWidget::getDefaultStateAttribute()
{
    return "SKGMONTHLY_DEFAULT_PARAMETERS";
}

QWidget* SKGMonthlyPluginWidget::mainWidget() const
{
    return ui.kWebView;
}

void SKGMonthlyPluginWidget::fillTemplateList()
{
    disconnect(ui.kTemplate, SIGNAL(currentIndexChanged(int)), this, SLOT(onMonthChanged()));
    //Get previous selected item
    QString current = ui.kTemplate->text();

    //Fill
    ui.kTemplate->clear();
    foreach(const QString & file, KStandardDirs().findAllResources("data", KGlobal::mainComponent().aboutData()->appName() % "/html/*.txt")) {
        QFileInfo f(file);
        QString file2 = f.completeBaseName();
        if (!ui.kTemplate->contains(file2) && file2 != "main") ui.kTemplate->addItem(file2, file);
    }

    //Set previous selected itemData
    if (!current.isEmpty() && ui.kTemplate->contains(current)) ui.kTemplate->setCurrentItem(current);
    connect(ui.kTemplate, SIGNAL(currentIndexChanged(int)), this, SLOT(onMonthChanged()), Qt::QueuedConnection);
}

void SKGMonthlyPluginWidget::onAddTemplate()
{
    QString templat = ui.kTemplate->text().trimmed();
    QString templatFileName = KStandardDirs::locateLocal("data", KGlobal::mainComponent().aboutData()->appName() % "/html/") % templat % ".txt";
    QStringList templates = KStandardDirs().findAllResources("data", KGlobal::mainComponent().aboutData()->appName() % "/html/*.txt");

    if (!templat.isEmpty() && (!templates.contains(templatFileName) || QFileInfo(templatFileName).isWritable())) {
        SKGError err;
        if (!templates.contains(templatFileName)) {
            //Create the new template
            QString source = KStandardDirs().findResource("data", KGlobal::mainComponent().aboutData()->appName() % "/html/default.txt");
            if (!KIO::NetAccess::file_copy(source, templatFileName)) {
                //Set error message
                err.setReturnCode(ERR_FAIL);
                err.setMessage(i18nc("An error message", "Impossible to copy file from '%1' to '%2'", source, templatFileName));
            } else {
                fillTemplateList();
            }
        }

        //Open the created or already existing file
        QDesktopServices::openUrl(KUrl(templatFileName));

        onTemplateChanged();

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

void SKGMonthlyPluginWidget::onDeleteTemplate()
{
    QString templat = ui.kTemplate->text().trimmed();
    QString templatFileName = KStandardDirs::locateLocal("data", KGlobal::mainComponent().aboutData()->appName() % "/html/") % templat % ".txt";
    if (!templat.isEmpty()) {
        //This is a new source
        SKGError err;

        //Delete the file
        QFile file(templatFileName);
        if (!file.remove()) {
            err.setReturnCode(ERR_INVALIDARG);
            err.setMessage(i18nc("Error message",  "Deletion of '%1' failed", templatFileName));
        }

        if (!err) ui.kTemplate->removeItem(ui.kTemplate->findText(templat));

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

void SKGMonthlyPluginWidget::onTemplateChanged()
{
    QString templat = ui.kTemplate->text().trimmed();
    QString templatFileName = KStandardDirs::locateLocal("data", KGlobal::mainComponent().aboutData()->appName() % "/html/") % templat % ".txt";
    bool local = !templat.isEmpty() && QFileInfo(templatFileName).isWritable();
    ui.kDeleteTemplate->setVisible(local);
    m_upload->setEnabled(local);
}

void SKGMonthlyPluginWidget::dataModified(const QString& iTableName, int iIdTransaction)
{
    SKGTRACEIN(1, "SKGMonthlyPluginWidget::dataModified");
    Q_UNUSED(iIdTransaction);

    QSqlDatabase* db = getDocument()->getDatabase();
    setEnabled(db != NULL);
    if (db != NULL && (iTableName == "v_operation_display" || iTableName.isEmpty())) {
        //Fill combo
        disconnect(ui.kMonth, SIGNAL(currentIndexChanged(int)), this, SLOT(onMonthChanged()));

        QStringList list;
        getDocument()->getDistinctValues("v_operation_display", "d_DATEMONTH", "d_date<=CURRENT_DATE", list);
        list.removeOne(QDate::currentDate().toString("yyyy-MM"));
        qSort(list.begin(), list.end(), qGreater<QString>());

        QString month = ui.kMonth->text();
        ui.kMonth->clear();
        ui.kMonth->addItem(i18nc("The month before the current month", "Last month"));
        ui.kMonth->addItems(list);
        if (!month.isEmpty()) ui.kMonth->setText(month);
        ui.kRefresh->setEnabled(list.count() > 0);
        connect(ui.kMonth, SIGNAL(currentIndexChanged(int)), this, SLOT(onMonthChanged()), Qt::QueuedConnection);

        onMonthChanged();
    }
}

QString SKGMonthlyPluginWidget::getMonth()
{
    QString month;
    if (month.isEmpty()) {
        if (ui.kMonth->currentIndex() == 0) {
            //Last month
            if (ui.kMonth->count() > 1) month = ui.kMonth->itemText(1);
        } else {
            //Specific month
            month = ui.kMonth->text();
        }
    }
    return month;
}

void SKGMonthlyPluginWidget::onMonthChanged()
{
    SKGTRACEIN(1, "SKGMonthlyPluginWidget::onMonthChanged");
    QString month = getMonth();
    if (!month.isEmpty()) {
        //Display report
        QString htmlReport = getDocument()->getParameter("SKG_MONTHLY_REPORT_" % month);
        if (htmlReport.isEmpty() || sender() == ui.kRefresh || sender() == ui.kTemplate) {
            SKGError err;
            SKGBEGINLIGHTTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Compute monthly report for '%1'", month), err);
            htmlReport = getReport();
            err = getDocument()->setParameter("SKG_MONTHLY_REPORT_" % month, htmlReport);
        }

        //Display html report
        ui.kWebView->setHtml(htmlReport);
        ui.kWebView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
    }
}

void SKGMonthlyPluginWidget::onGetNewHotStuff()
{
    QPointer<KNS3::DownloadDialog> dialog = new KNS3::DownloadDialog(KGlobal::mainComponent().aboutData()->appName() % "_monthly.knsrc", this);
    dialog->exec();
    delete dialog;

    fillTemplateList();
}

void SKGMonthlyPluginWidget::onPutNewHotStuff()
{
    QString templat = ui.kTemplate->text().trimmed();

    //Create zip file
    QString templatFileName = KStandardDirs::locateLocal("data", KGlobal::mainComponent().aboutData()->appName() % "/html/") % templat % ".txt";
    QString templatHFileName = KStandardDirs::locateLocal("data", KGlobal::mainComponent().aboutData()->appName() % "/html/") % templat % ".html";
    QString zipFileName = QDir::tempPath() % "/" % templat % ".zip";
    KZip zip(zipFileName);
    if (zip.open(QIODevice::WriteOnly)) {
        zip.addLocalFile(templatFileName, templat % ".txt");
        if (QFile(templatHFileName).exists()) zip.addLocalFile(templatHFileName, templat % ".html");
        zip.close();

        //Create screen shots
        QWebFrame* frame = ui.kWebView->page()->mainFrame();
        QString preview2 = QDir::tempPath() % "/" % templat % "_preview2.png";
        frame->setScrollBarValue(Qt::Vertical, frame->scrollBarMaximum(Qt::Vertical));
        ui.kWebView->exportInFile(preview2);

        QString preview3 = QDir::tempPath() % "/" % templat % "_preview3.png";
        frame->setScrollBarValue(Qt::Vertical, frame->scrollBarMaximum(Qt::Vertical) / 2);
        ui.kWebView->exportInFile(preview3);

        QString preview1 = QDir::tempPath() % "/" % templat % "_preview1.png";
        frame->setScrollBarValue(Qt::Vertical, 0);
        ui.kWebView->exportInFile(preview1);

        //Open dialog
        QPointer<KNS3::UploadDialog> dialog = new KNS3::UploadDialog(KGlobal::mainComponent().aboutData()->appName() % "_monthly.knsrc", this);

        dialog->setUploadFile(zipFileName);
        dialog->setUploadName(templat);
#ifdef SKGKDE46ENABLED
        dialog->setPreviewImageFile(0, KUrl(preview1));
        dialog->setPreviewImageFile(1, KUrl(preview2));
        dialog->setPreviewImageFile(2, KUrl(preview3));
#endif
        dialog->setDescription(i18nc("Default description for a monthly report template", "My favorite template"));
        dialog->exec();
        delete dialog;

        //Delete temporary files
        QFile(zipFileName).remove();
        QFile(preview1).remove();
        QFile(preview2).remove();
        QFile(preview3).remove();
    }
}

void SKGMonthlyPluginWidget::onOpen(const QUrl& iLink)
{
    //Call operation plugin
    QDomDocument doc("SKGML");

    QStringList params = SKGServices::splitCSVLine(iLink.toString());
    if (params.count() == 2) {
        //Open special page
        doc.setContent(getDocument()->getParameter(params.at(1)));
        QDomElement root = doc.documentElement();
        if (root.isNull()) {
            root = doc.createElement("parameters");
            doc.appendChild(root);
        }
        SKGMainPanel::getMainPanel()->openPage(SKGMainPanel::getMainPanel()->getPluginByName(params.at(0)), -1, doc.toString());
    } else {
        //Open URL
        QDesktopServices::openUrl(iLink);
    }
}

QString SKGMonthlyPluginWidget::getReport()
{
    QString html;
    SKGError err;
    SKGTRACEINRC(10, "SKGMonthlyPluginWidget::getReport", err);
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

    //Get month
    if (!getMonth().isEmpty()) {
        SKGReport* rep = getDocument()->getReport();
        if (rep) {
            rep->setMonth(getMonth());
            err = rep->getReportFormTemplate(rep, ui.kTemplate->itemData(ui.kTemplate->currentIndex()).toString(), html);

            delete rep;
        }
    }
    QApplication::restoreOverrideCursor();

    //status bar
    if (err) html += err.getFullMessageWithHistorical();
    return html;
}

#include "skgmonthlypluginwidget.moc"
