/* ============================================================
* GreaseMonkey plugin for QupZilla
* Copyright (C) 2012  David Rosca <nowrep@gmail.com>
*
* 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 3 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/>.
* ============================================================ */
#include "gm_downloader.h"
#include "gm_addscriptdialog.h"
#include "gm_manager.h"
#include "gm_script.h"

#include "webpage.h"
#include "followredirectreply.h"
#include "mainapplication.h"
#include "networkmanager.h"
#include "globalfunctions.h"

#include <QFile>
#include <QSettings>
#include <QRegExp>
#include <QDebug>

GM_Downloader::GM_Downloader(const QNetworkRequest &request, GM_Manager* manager)
    : QObject()
    , m_manager(manager)
{
    m_reply = new FollowRedirectReply(request.url(), mApp->networkManager());
    connect(m_reply, SIGNAL(finished()), this, SLOT(scriptDownloaded()));

    QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100));
    WebPage* webPage = static_cast<WebPage*>(v.value<void*>());
    if (WebPage::isPointerSafeToUse(webPage)) {
        m_widget = webPage->view();
    }
}

void GM_Downloader::scriptDownloaded()
{
    if (m_reply != qobject_cast<FollowRedirectReply*>(sender())) {
        deleteLater();
        return;
    }

    QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8();

    if (m_reply->error() == QNetworkReply::NoError && response.contains("// ==UserScript==")) {
        const QString &filePath = m_manager->scriptsDirectory() + qz_getFileNameFromUrl(m_reply->url());
        m_fileName = qz_ensureUniqueFilename(filePath);

        QFile file(m_fileName);

        if (!file.open(QFile::WriteOnly)) {
            qWarning() << "GreaseMonkey: Cannot open file for writing" << m_fileName;
            deleteLater();
            return;
        }

        file.write(response);
        file.close();

        QSettings settings(m_manager->settinsPath() + "greasemonkey/requires/requires.ini", QSettings::IniFormat);
        settings.beginGroup("Files");

        QRegExp rx("@require(.*)\\n");
        rx.setMinimal(true);
        rx.indexIn(response);

        for (int i = 1; i <= rx.captureCount(); ++i) {
            const QString &url = rx.cap(i).trimmed();
            if (!url.isEmpty() && !settings.contains(url)) {
                m_requireUrls.append(QUrl(url));
            }
        }
    }

    m_reply->deleteLater();
    m_reply = 0;

    downloadRequires();
}

void GM_Downloader::requireDownloaded()
{
    if (m_reply != qobject_cast<FollowRedirectReply*>(sender())) {
        deleteLater();
        return;
    }

    QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8();

    if (m_reply->error() == QNetworkReply::NoError && !response.isEmpty()) {
        const QString &filePath = m_manager->settinsPath() + "/greasemonkey/requires/require.js";
        const QString &fileName = qz_ensureUniqueFilename(filePath, "%1");

        QFile file(fileName);

        if (!file.open(QFile::WriteOnly)) {
            qWarning() << "GreaseMonkey: Cannot open file for writing" << fileName;
            deleteLater();
            return;
        }

        file.write(response);
        file.close();

        QSettings settings(m_manager->settinsPath() + "greasemonkey/requires/requires.ini", QSettings::IniFormat);
        settings.beginGroup("Files");
        settings.setValue(m_reply->originalUrl().toString(), fileName);
    }

    m_reply->deleteLater();
    m_reply = 0;

    downloadRequires();
}

void GM_Downloader::downloadRequires()
{
    if (!m_requireUrls.isEmpty()) {
        m_reply = new FollowRedirectReply(m_requireUrls.takeFirst(), mApp->networkManager());
        connect(m_reply, SIGNAL(finished()), this, SLOT(requireDownloaded()));
    }
    else {
        bool deleteScript = true;
        GM_Script* script = new GM_Script(m_manager, m_fileName);

        if (script->isValid()) {
            if (!m_manager->containsScript(script->fullName())) {
                GM_AddScriptDialog dialog(m_manager, script, m_widget);
                deleteScript = dialog.exec() != QDialog::Accepted;
            }
            else {
                m_manager->showNotification(tr("'%1' is already installed").arg(script->name()));
            }
        }

        if (deleteScript) {
            delete script;
            QFile(m_fileName).remove();
        }

        deleteLater();
    }
}
