/*******************************************************************************
 **
 ** smolbote: yet another qute browser
 ** Copyright (C) 2017  Xian Nox
 **
 ** 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 .
 **
 ******************************************************************************/
#include "blockersubscription.h"
#include "ui_subscriptionform.h"
#include "browser.h"
#include 
#include 
BlockerSubscription::BlockerSubscription(const QUrl url, QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SubscriptionForm)
{
    ui->setupUi(this);
    m_name = url.fileName();
    m_url = url;
    QString subPath = sSettings->value("blocker.path").toString() + m_name;
    qDebug("Adding subscription [%s]", qUtf8Printable(subPath));
    QFile *sub = new QFile(subPath);
    if(sub->exists()) {
        sub->open(QIODevice::ReadOnly);
        load(sub);
    } else {
        if(!url.scheme().startsWith("http")) {
            qWarning("Invalid url, subscription cannot be updated");
            sub->deleteLater();
            return;
        }
        qDebug("Subscription doesn't exist, updating...");
        sub->open(QIODevice::ReadWrite);
        update(sub);
    }
}
BlockerSubscription::~BlockerSubscription()
{
    delete ui;
}
QString BlockerSubscription::name() const
{
    return m_name;
}
/**
 * Check if a URL request should be blocked or not
 * @param info
 * @return true if it should be blocked; false otherwise
 */
BlockerSubscription::MatchResult BlockerSubscription::match(QWebEngineUrlRequestInfo &info)
{
    MatchResult result;
    for(BlockerRule* rule : m_urlWhitelist) {
        if(rule->match(info)) {
            // this request is whitelisted
            result.match = true;
            result.block = false;
            result.pattern = rule->filter();
            return result;
        }
    }
    // request is not in the whitelist
    for(BlockerRule* rule : m_urlBlacklist) {
        if(rule->match(info)) {
            // this request is blacklisted
            result.match = true;
            result.block = true;
            result.pattern = rule->filter();
            return result;
        }
    }
    // request matches neither whitelist nor blacklist
    result.match = false;
    result.block = false;
    return result;
}
void BlockerSubscription::update(QFile *cache)
{
    // no cache path specified - pull the subscription
    QNetworkRequest request;
    request.setUrl(m_url);
    QNetworkReply *reply = sNetwork->get(request);
    connect(reply, &QNetworkReply::readyRead, [this, reply, cache]() {
        cache->write(reply->readAll());
    });
    connect(reply, &QNetworkReply::finished, [this, reply, cache]() {
        cache->write(reply->readAll());
        cache->flush();
        cache->seek(0);
        reply->deleteLater();
        qDebug("Subscription updated: [%s]", qUtf8Printable(this->m_name));
        this->load(cache);
    });
}
void BlockerSubscription::load(QIODevice *dev)
{
    QTextStream subscription(dev);
    QString header = subscription.readLine();
    if(!header.startsWith("[Adblock Plus")) {
        qWarning("Invalid format of subscription: %s", qUtf8Printable(m_name));
    }
    // clear all lists
    m_urlBlacklist.clear();
    m_urlWhitelist.clear();
    int rules = 0;
    while(!subscription.atEnd()) {
        QString line = subscription.readLine();
        if(!line.isEmpty()) {
            if(line.startsWith('!')) {
                parseComment(line);
            } else {
                // The line is not empty or a comment
                rules++;
                BlockerRule *rule = new BlockerRule(line, this);
                if(rule->isValid()) {
                    if(rule->isException()) {
                        m_urlWhitelist.append(rule);
                        ui->whitelist_listWidget->addItem(rule->filter());
                    } else {
                        ui->blacklist_listWidget->addItem(rule->filter());
                        m_urlBlacklist.append(rule);
                    }
                }
            }
        } // line.isEmpty
    } // subscription.atEnd()
    qDebug("Loaded %i/%i rules from subscription %s", m_urlBlacklist.count() + m_urlWhitelist.count(), rules, qUtf8Printable(m_name));
    dev->deleteLater();
}
void BlockerSubscription::parseComment(const QString &line)
{
    if(line.startsWith("! Title: ")) {
        ui->title->setText(line.right(line.length() - 9));
        return;
    }
    if(line.startsWith("! Homepage: ")) {
        ui->homepage->setText(line.right(line.length() - 12));
        return;
    }
    if(line.startsWith("! Licence: ")) {
        ui->license->setText(line.right(line.length() - 11));
        return;
    }
    if(line.startsWith("! Version: ")) {
        ui->version->setText(line.right(line.length() - 11));
        return;
    }
    if(line.startsWith("! Last modified: ")) {
        ui->lastModified->setText(line.right(line.length() - 17));
        return;
    }
    if(line.startsWith("! Expires: ")) {
        ui->expires->setText(line.right(line.length() - 11).left(2));
        return;
    }
}