/***************************************************************************
 *   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 <KStandardDirs>
#include <knewstuff3/downloaddialog.h>
#include <knewstuff3/uploaddialog.h>
#include <KMenu>
#include <KZip>
#include <KComponentData>
#include <KAboutData>

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

#include "skgmainpanel.h"
#include "skgtraces.h"
#include "skgreport.h"
#include "skgtransactionmng.h"

SKGMonthlyPluginWidget::SKGMonthlyPluginWidget(SKGDocument* iDocument)
    : SKGTabPage(iDocument)
{
    SKGTRACEINFUNC(1);
    if (!iDocument) {
        return;
    }

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

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

    connect(getDocument(), SIGNAL(tableModified(QString,int,bool)), 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)), SKGMainPanel::getMainPanel(), SLOT(openPage(QUrl)));

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

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

SKGMonthlyPluginWidget::~SKGMonthlyPluginWidget()
{
    SKGTRACEINFUNC(1);
}

QString SKGMonthlyPluginWidget::getState()
{
    SKGTRACEINFUNC(10);
    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)
{
    SKGTRACEINFUNC(10);
    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()
{
    return ui.kWebView;
}

void SKGMonthlyPluginWidget::fillTemplateList()
{
    disconnect(ui.kTemplate, SIGNAL(currentIndexChanged(int)), this, SLOT(onPeriodChanged()));
    // 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(onPeriodChanged()), 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 (SKGServices::upload(source, templatFileName)) {
                err.setReturnCode(ERR_FAIL).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).setMessage(i18nc("Error message",  "Deletion of '%1' failed", templatFileName));
        }

        IFOK(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)
{
    SKGTRACEINFUNC(1);
    Q_UNUSED(iIdTransaction);

    QSqlDatabase* db = getDocument()->getDatabase();
    setEnabled(db != NULL);
    // TODO(Stephane MANKOWSKI): v_operation_display must be generic
    if (db != NULL && (iTableName == "v_operation_display" || iTableName.isEmpty())) {
        // Fill combo
        disconnect(ui.kMonth, SIGNAL(currentIndexChanged(int)), this, SLOT(onPeriodChanged()));

        QStringList list;
        getDocument()->getDistinctValues("v_operation_display", "MIN(d_DATEMONTH)", "d_date<=CURRENT_DATE", list);
        if (list.count()) {
            if (!list[0].isEmpty()) {
                QDate c = SKGServices::periodToDate(list[0]);
                c = c.addDays(1 - c.day());

                QDate today = QDate::currentDate();
                QString smonth = SKGServices::dateToPeriod(today, "M");
                QString squater = SKGServices::dateToPeriod(today, "Q");
                QString ssemester = SKGServices::dateToPeriod(today, "S");
                QString syear = SKGServices::dateToPeriod(today, "Y");

                // Build the list
                list.clear();
                do {
                    QString cmonth = SKGServices::dateToPeriod(c, "M");
                    QString cquater = SKGServices::dateToPeriod(c, "Q");
                    QString csemester = SKGServices::dateToPeriod(c, "S");
                    QString cyear = SKGServices::dateToPeriod(c, "Y");
                    if (cmonth != smonth) {
                        list.insert(0, cmonth);
                    }
                    if (c.month() % 3 == 0 && cquater != squater) {
                        list.insert(0, cquater);
                    }
                    if (c.month() % 6 == 0 && csemester != ssemester) {
                        list.insert(0, csemester);
                    }
                    if (c.month() == 12 && cyear != syear) {
                        list.insert(0, cyear);
                    }

                    c = c.addMonths(1);

                    if (cmonth == smonth || c >= today) {
                        break;
                    }
                } while (true);
            }
        }

        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(onPeriodChanged()), Qt::QueuedConnection);

        onPeriodChanged();
    }
}

QString SKGMonthlyPluginWidget::getPeriod()
{
    QString month;
    if (month.isEmpty()) {
        if (ui.kMonth->currentIndex() == 0) {
            // Last month
            if (ui.kMonth->count() > 1) {
                QDate today = QDate::currentDate();
                month = today.addDays(1 - today.day()).addMonths(-1).toString("yyyy-MM");
            }
        } else {
            // Specific month
            month = ui.kMonth->text();
        }
    }
    return month;
}

void SKGMonthlyPluginWidget::onPeriodChanged()
{
    SKGTRACEINFUNC(1);
    QString month = getPeriod();
    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);
        dialog->setPreviewImageFile(0, KUrl(preview1));
        dialog->setPreviewImageFile(1, KUrl(preview2));
        dialog->setPreviewImageFile(2, KUrl(preview3));
        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();
    }
}

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

    // Get period
    if (!getPeriod().isEmpty()) {
        SKGReport* rep = getDocument()->getReport();
        if (rep) {
            rep->setPeriod(getPeriod());
            err = rep->getReportFromTemplate(rep, ui.kTemplate->itemData(ui.kTemplate->currentIndex()).toString(), html);

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

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

#include "skgmonthlypluginwidget.moc"
