/***************************************************************************
 *   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 report class for document
 *
 * @author Stephane MANKOWSKI
 */
#include "skgreport.h"

#include <grantlee/engine.h>
#include <grantlee/templateloader.h>
#include <grantlee/qtlocalizer.h>
#include <grantlee/metatype.h>

#include <kaboutdata.h>
#include <kcolorscheme.h>

#include <qfile.h>
#include <qdir.h>
#include <qfont.h>
#include <qstandardpaths.h>
#include <qurl.h>
#include <qfontdatabase.h>

#include "skgtraces.h"
#include "skgdocument.h"
#include "skgobjectbase.h"

GRANTLEE_BEGIN_LOOKUP(SKGObjectBase)
Q_UNUSED(object);
Q_UNUSED(property);
GRANTLEE_END_LOOKUP

SKGReport::SKGReport(SKGDocument* iDocument)
    : QObject(), m_document(iDocument), m_previous(nullptr)
{
    SKGTRACEINFUNC(1);

    // Grantlee initialization
    Grantlee::registerMetaType<SKGObjectBase>();
}

SKGReport::~SKGReport()
{
    SKGTRACEINFUNC(1);
    if (m_previous) {
        delete m_previous;
        m_previous = nullptr;
    }
}

void SKGReport::setPeriod(const QString& iPeriod)
{
    if (iPeriod != m_cache[QStringLiteral("period")]) {
        cleanCache(false);
        if (m_previous) {
            delete m_previous;
            m_previous = nullptr;
        }
        m_cache[QStringLiteral("period")] = iPeriod;
        emit changed();
    }
}

QString SKGReport::getPeriod()
{
    QString month = m_cache.value(QStringLiteral("period")).toString();
    if (month.isEmpty()) {
        month = QDate::currentDate().toString(QStringLiteral("yyyy-MM"));
        m_cache[QStringLiteral("period")] = month;
    }
    return month;
}

QString SKGReport::getPreviousPeriod()
{
    QString previousmonth = m_cache.value(QStringLiteral("previousperiod")).toString();
    if (previousmonth.isEmpty()) {
        QString period = getPeriod();
        if (!period.isEmpty()) {
            previousmonth = SKGServices::getNeighboringPeriod(period);
        }
        m_cache[QStringLiteral("previousperiod")] = previousmonth;
    }
    return previousmonth;
}

SKGReport* SKGReport::getPrevious()
{
    if (m_previous == nullptr) {
        m_previous = m_document->getReport();
        m_previous->setPeriod(getPreviousPeriod());
    }
    return m_previous;
}

QVariantHash SKGReport::getContextProperty()
{
    QVariantHash mapping;
    addItemsInMapping(mapping);

    if (m_document) {
        mapping.insert(QStringLiteral("document"), QVariant::fromValue<QObject*>(m_document));
    }
    return mapping;
}

void SKGReport::addItemsInMapping(QVariantHash& iMapping)
{
    iMapping.insert(QStringLiteral("report"), QVariant::fromValue<QObject*>(this));
    iMapping.insert(QStringLiteral("current_date"), QDate::currentDate());
    KColorScheme scheme(QPalette::Normal, KColorScheme::Window);
    iMapping.insert(QStringLiteral("color_negativetext"), scheme.foreground(KColorScheme::NegativeText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_positivetext"), scheme.foreground(KColorScheme::PositiveText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_neutraltext"), scheme.foreground(KColorScheme::NeutralText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_normaltext"), scheme.foreground(KColorScheme::NormalText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_inactivetext"), scheme.foreground(KColorScheme::InactiveText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_activetext"), scheme.foreground(KColorScheme::ActiveText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_linktext"), scheme.foreground(KColorScheme::LinkText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_visitedtext"), scheme.foreground(KColorScheme::VisitedText).color().name().right(6));
    iMapping.insert(QStringLiteral("color_normalbackground"), scheme.background(KColorScheme::NormalBackground).color().name().right(6));
    iMapping.insert(QStringLiteral("color_activebackground"), scheme.background(KColorScheme::ActiveBackground).color().name().right(6));

    QFont generalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont);
    iMapping.insert(QStringLiteral("font_family"), generalFont.family());

    QString dir = "file://" % QFileInfo(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/infopage/kde_infopage.css"))).dir().absolutePath() % '/';
    {
        QFile file(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/infopage/kde_infopage.css")));
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            iMapping.insert(QStringLiteral("kde_infopage_css"), QString(file.readAll()).replace(QStringLiteral("url("), "url(" % dir));
        }
    }

    KAboutData about = KAboutData::applicationData();
    iMapping.insert(QStringLiteral("about_welcome"), i18nc("Welcome message", "Welcome to %1", about.displayName()));
    iMapping.insert(QStringLiteral("about_programname"), about.displayName());
    iMapping.insert(QStringLiteral("about_version"), about.version());
    iMapping.insert(QStringLiteral("about_bugaddress"), about.bugAddress());
    iMapping.insert(QStringLiteral("about_copyrightstatement"), about.copyrightStatement());
    iMapping.insert(QStringLiteral("about_homepage"), about.homepage());
    iMapping.insert(QStringLiteral("about_shortdescription"), about.shortDescription());
    iMapping.insert(QStringLiteral("about_othertext"), about.otherText());
}

SKGError SKGReport::getReportFromTemplate(SKGReport* iReport, const QString& iFile, QString& oHtml)
{
    SKGError err;
    SKGTRACEINFUNCRC(10, err);

    // Prepare grantlee engine
    Grantlee::Engine gEngine;
    gEngine.addDefaultLibrary(QStringLiteral("grantlee_skgfilters"));

    QSharedPointer<Grantlee::FileSystemTemplateLoader> gLoader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader());
    gLoader->setTemplateDirs(QStringList(QFileInfo(iFile).dir().absolutePath()));
    gEngine.addTemplateLoader(gLoader);

    Grantlee::Template gTemplate = gEngine.loadByName(QFileInfo(iFile).fileName());
    if (gTemplate->error()) {
        err = SKGError(gTemplate->error(), gTemplate->errorString());
    } else {
        QVariantHash mapping;
        if (iReport) {
            mapping = iReport->getContextProperty();
        }
        Grantlee::Context gContext(mapping);

        // Generation
        {
            SKGTRACEINFUNCRC(10, err);
            oHtml = gTemplate->render(&gContext);
            if (gTemplate->error()) {
                err = SKGError(gTemplate->error(), gTemplate->errorString());
            }
        }
    }
    return err;
}

void SKGReport::cleanCache(bool iEmitSignal)
{
    QString month = m_cache.value(QStringLiteral("period")).toString();
    m_cache.clear();
    if (!month.isEmpty()) {
        m_cache[QStringLiteral("period")] = month;
    }
    if (iEmitSignal) {
        emit changed();
    }
}
