/***************************************************************************
 *   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 to generate statistic
 *
 * @author Stephane MANKOWSKI
 */
#include "skgstatisticplugin.h"

#ifdef HAVE_UNAME
# include <sys/utsname.h>
#endif

#include <KActionCollection>
#include <KStandardAction>
#include <kaboutdata.h>
#include <kpluginfactory.h>
#include <qdir.h>
#include <QCryptographicHash>
#include <qapplication.h>
#include <QDesktopWidget>
#include <QJsonDocument>

#include "skgtraces.h"
#include "skgmainpanel.h"

/**
 * This plugin factory.
 */
K_PLUGIN_FACTORY(SKGStatisticPluginFactory, registerPlugin<SKGStatisticPlugin>();)

SKGStatisticPlugin::SKGStatisticPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& /*iArg*/) :
    SKGInterfacePlugin(iParent), m_currentDocument(NULL)
{
    Q_UNUSED(iWidget);
    m_timeInit = QDateTime::currentDateTime();
    SKGTRACEINFUNC(10);

    connect(SKGMainPanel::getMainPanel(), &SKGMainPanel::currentPageChanged, this, &SKGStatisticPlugin::pageChanged);
    connect(SKGMainPanel::getMainPanel(), &SKGMainPanel::pageOpened, this, &SKGStatisticPlugin::pageOpened);
}

SKGStatisticPlugin::~SKGStatisticPlugin()
{
    SKGTRACEINFUNC(10);
    // Set duration
    m_stats["avg.exec_time_sec"] = (m_stats["avg.exec_time_sec"].toDouble() * (m_stats["nb_launch"].toInt() - 1) + m_timeInit.secsTo(QDateTime::currentDateTime())) / m_stats["nb_launch"].toInt();

    // Write stat file
    writeStats();

    m_currentDocument = NULL;
}

bool SKGStatisticPlugin::setupActions(SKGDocument* iDocument, const QStringList& iArgument)
{
    SKGTRACEINFUNC(10);
    Q_UNUSED(iArgument);

    m_currentDocument = iDocument;

    setComponentName("skg_statistic", title());
    setXMLFile("skg_statistic.rc");

    // Connect actions
    /*QMap<QString, QPointer<QAction> > actions = SKGMainPanel::getMainPanel()->getGlobalActions();
    QStringList keys = actions.keys();
    foreach(const QString & k, keys) {
        QPointer<QAction> act = actions[k];
        connect(act.data(), &QAction::triggered, this, &SKGStatisticPlugin::triggerAction);
    }*/

    return true;
}

void SKGStatisticPlugin::refresh()
{
    SKGTRACEINFUNC(10);
    if (m_currentDocument) {
        if (m_currentDocument->getDatabase() != NULL) {
            QString doc_id = m_currentDocument->getUniqueIdentifier();
            if (m_docUniqueIdentifier != doc_id) {
                m_docUniqueIdentifier = doc_id;

                // Initialize
                QString appname = KAboutData::applicationData().componentName();
                QDir::home().mkdir("." % appname);
                QString docUUID = QString(QCryptographicHash::hash(m_currentDocument->getCurrentFileName().toLatin1(), QCryptographicHash::Md5).toHex());
                m_file = QDir::homePath() % "/." % appname % "/" % docUUID % ".stats.txt";

                // Read previous stat file
                readStats();

                // Initial values
                if (!m_stats.contains("init.date")) {
                    m_stats["init.date"] = QDate::currentDate();
                    m_stats["init.qt_version"] = qVersion();
                    m_stats["init.app_name"] = appname;
                    m_stats["init.app_version"] = KAboutData::applicationData().version();
                }
                m_stats["nb_launch"] = m_stats["nb_launch"].toInt() + 1;

                // Current values
                m_stats["current.date"] = QDate::currentDate();
                m_stats["current.qt_version"] = qVersion();
                m_stats["current.app_version"] = KAboutData::applicationData().version();
                m_stats["current.language"] = QLocale::languageToString(QLocale().language());
                m_stats["current.country"] = QLocale::countryToString(QLocale().country());

                // OS
#ifdef Q_OS_WIN32
                QString os = "Windows";
#elseifdef Q_OS_FREEBSD
                QString os = "FreeBSD";
#elseifdef Q_OS_NETBSD
                QString os = "NetBSD";
#elseifdef Q_OS_OPENBSD
                QString os = "OpenBSD";
#elseifdef Q_OS_LINUX
                QString os = "Linux";
#elseifdef Q_OS_MAC
                QString os = "Mac OS";
#else
                QString os = "Unknow";
#endif
                m_stats["current.os"] = os;
                QRect scr = QApplication::desktop()->screenGeometry();
                m_stats["current.screen"] = QString(SKGServices::intToString(scr.width()) % 'x' % SKGServices::intToString(scr.height()));

#ifdef HAVE_UNAME
                struct utsname buf;
                if (uname(&buf) != -1) {
                    m_stats["current.os.machine"] = QString::fromLocal8Bit(buf.machine);
                    m_stats["current.os.version"] = QString::fromLocal8Bit(buf.version);
                }
#endif

                // Nb calls
                QMap<QString, QPointer<QAction> > actions = SKGMainPanel::getMainPanel()->getGlobalActions();
                QStringList keys = actions.keys();
                foreach(const QString & k, keys) {
                    QPointer<QAction> act = actions[k];
                    if (act) {
                        QString id = "nb_call." % act->objectName();
                        if (!m_stats.contains(id)) {
                            m_stats[id] = 0;
                        }
                    }
                }
                m_stats["document.uuid"] = docUUID;

                // Set tables sizes
                QStringList tables;
                m_currentDocument->getTablesList(tables);
                foreach(const QString & t, tables) {
                    QString r;
                    m_currentDocument->executeSingleSelectSqliteOrder("SELECT COUNT(1) FROM " % t, r);
                    m_stats["count." % t] = SKGServices::stringToInt(r);
                }
            }
        }
    }
}

void SKGStatisticPlugin::readStats()
{
    m_stats.clear();

    // Read file
    QFile data(m_file);
    if (data.open(QFile::ReadOnly)) {
        // Parse json
        m_stats = QJsonDocument::fromJson(data.readAll()).toVariant().toMap();
        data.close();
    }
}

void SKGStatisticPlugin::writeStats()
{
    // Write it in file
    QFile data(m_file);
    if (data.open(QFile::WriteOnly | QFile::Truncate)) {
        // serialize json
        QJsonDocument serializer = QJsonDocument::fromVariant(m_stats);
        QByteArray doc = serializer.toJson(QJsonDocument::Compact);

        data.write(doc);
        data.close();
    }
}

void SKGStatisticPlugin::triggerAction()
{
    QAction* act = qobject_cast< QAction* >(sender());
    if (act) {
        QString id = "nb_call." % act->objectName();
        m_stats[id] = m_stats[id].toInt() + 1;
    }
}

void SKGStatisticPlugin::pageChanged()
{
    SKGTabPage::SKGPageHistoryItem currentPage = SKGMainPanel::getMainPanel()->currentPageHistoryItem();
    if (!currentPage.plugin.isEmpty()) {
        QString id = "nb_activated_" % QString(currentPage.bookmarkID.isEmpty() ? "page" : "bookmark") % "." % currentPage.plugin;
        m_stats[id] = m_stats[id].toInt() + 1;
    }
}

void SKGStatisticPlugin::pageOpened()
{
    SKGTabPage::SKGPageHistoryItem currentPage = SKGMainPanel::getMainPanel()->currentPageHistoryItem();
    if (!currentPage.plugin.isEmpty()) {
        QString id = "nb_opened_" % QString(currentPage.bookmarkID.isEmpty() ? "page" : "bookmark") % "." % currentPage.plugin;
        m_stats[id] = m_stats[id].toInt() + 1;
    }
}

QString SKGStatisticPlugin::title() const
{
    return i18nc("The title", "Statistic");
}

QString SKGStatisticPlugin::icon() const
{
    return "dialog-information";
}

QString SKGStatisticPlugin::toolTip() const
{
    return title();
}

int SKGStatisticPlugin::getOrder() const
{
    return 9999;
}

bool SKGStatisticPlugin::isInPagesChooser() const
{
    return false;
}

#include <skgstatisticplugin.moc>
