#include <QDir>
#include <QFile>
#include <QTextStream>

#include "dcantispam.h"

DCAntiSpam *DCAntiSpam::g_pAntiSpam = NULL;

DCAntiSpam::DCAntiSpam() {
    try_count = 0;
}

DCAntiSpam::~DCAntiSpam() {
    gray_list.clear();
    white_list.clear();
    black_list.clear();
}

void DCAntiSpam::slotObjectChangeState(QString obj, AntiSpamObjectState from, AntiSpamObjectState to) {
    if (from == to)
        return;

    if ((from == eIN_BLACK && !black_list.contains(obj)) ||
            (from == eIN_WHITE && !white_list.contains(obj)) ||
            (from == eIN_GRAY && !gray_list.contains(obj))) {
        return;
    }

    QList<QString> *from_list = &white_list;
    QList<QString> *to_list = &black_list;

    if (from != eIN_WHITE) {
        if (from == eIN_BLACK)
            from_list = &black_list;
        else
            from_list = &gray_list;
    }\

    if (to != eIN_BLACK) {
        if (to == eIN_WHITE)
            to_list = &white_list;
        else
            to_list = &gray_list;
    }

    from_list->removeAll(obj);

    if (to_list->contains(obj)) {//just remove from source list
        return;
    }

    to_list->append(obj);

}

bool DCAntiSpam::isInAny(QString obj) {
    return ( isInBlack(obj) || isInGray(obj) || isInWhite(obj));
}

bool DCAntiSpam::isInBlack(QString obj) {
    return (black_list.contains(obj));
}

bool DCAntiSpam::isInGray(QString obj) {
    return ( gray_list.contains(obj));
}

bool DCAntiSpam::isInWhite(QString obj) {
    return ( white_list.contains(obj));
}

void DCAntiSpam::move(QString obj, AntiSpamObjectState state) {
    if (isInAny(obj)) {
        AntiSpamObjectState from;

        if (isInBlack(obj))
            from = eIN_BLACK;
        else if (isInGray(obj))
            from = eIN_GRAY;
        else
            from = eIN_WHITE;

        slotObjectChangeState(obj, from, state);
    } else {
        if (state == eIN_BLACK)
            black_list << obj;
        else if (state == eIN_GRAY)
            gray_list << obj;
        else
            white_list << obj;
    }
}

inline void DCAntiSpam::addToList(QList<QString> &source, QList<QString> &dest) {
    for (int i = 0; i < dest.size(); i++) {
        if (!source.contains(dest.at(i)))
            source << dest.at(i);
    }
}

inline void DCAntiSpam::remFromList(QList<QString> &from, QList<QString> &what) {
    for (int i = 0; i < what.size(); i++) {
        int index = from.indexOf(what.at(i));

        if (index != -1)
            from.removeAt(index);
    }
}

void DCAntiSpam::addToBlack(QList<QString> &list) {
    addToList(black_list, list);
}

void DCAntiSpam::addToGray(QList<QString> &list) {
    addToList(gray_list, list);
}

void DCAntiSpam::addToWhite(QList<QString> &list) {
    addToList(white_list, list);
}

void DCAntiSpam::remFromBlack(QList<QString> &list) {
    remFromList(black_list, list);
}

void DCAntiSpam::remFromGray(QList<QString> &list) {
    remFromList(gray_list, list);
}

void DCAntiSpam::remFromWhite(QList<QString> &list) {
    remFromList(white_list, list);
}

QList<QString> DCAntiSpam::getBlack() {
    return black_list;
}

QList<QString> DCAntiSpam::getGray() {
    return gray_list;
}

QList<QString> DCAntiSpam::getWhite() {
    return white_list;
}

void DCAntiSpam::loadLists() {
    if (!gray_list.empty() ||
            !black_list.empty() ||
            !white_list.empty()) {
        return;
    }
    loadBlack();
    loadWhite();
    loadGray();
}

void DCAntiSpam::saveLists() {
    saveBlack();
    saveGray();
    saveWhite();
}

void DCAntiSpam::loadBlack() {
    readFile(QDir::homePath() + "/.eiskaltdc/blacklist", black_list);
}

void DCAntiSpam::loadGray() {
    readFile(QDir::homePath() + "/.eiskaltdc/graylist", gray_list);
}

void DCAntiSpam::loadWhite() {
    readFile(QDir::homePath() + "/.eiskaltdc/whitelist", white_list);
}

void DCAntiSpam::saveBlack() {
    saveFile(QDir::homePath() + "/.eiskaltdc/blacklist", black_list);
}

void DCAntiSpam::saveGray() {
    saveFile(QDir::homePath() + "/.eiskaltdc/graylist", gray_list);
}

void DCAntiSpam::saveWhite() {
    saveFile(QDir::homePath() + "/.eiskaltdc/whitelist", white_list);
}

void DCAntiSpam::readFile(QString path, QList<QString> &list) {
    if (!QFile::exists(path))
        return;

    QFile file(path);

    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    QTextStream in(&file);

    while (!in.atEnd()) {
        QString line = in.readLine();

        line.replace("\n", "");

        if (line == "")
            continue;

        list << line;
    }

    file.close();
}

void DCAntiSpam::saveFile(QString path, QList<QString> &list) {
    QFile file(path);

    if (!file.open(QIODevice::WriteOnly))
        return;

    QTextStream out(&file);

    for (int i = 0; i < list.size(); i++)
        out << list.at(i) << "\n";

    file.close();
}

void DCAntiSpam::loadSettings() {
    QFile file(QDir::homePath() + "/.eiskaltdc/antispam");

    if (!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)) {
	keys.append("10");
        phrase = "5+5=?";

        return;
    }

    QTextStream in(&file);

    while (!in.atEnd()) {
        QString line = in.readLine();

        if (line.indexOf("|ANTISPAM_PHRASE|") != -1) {
            line = line.right(line.length() - 17);
            line.replace("\n", "");

            if (line == "")
                phrase = "5+5=?";
            else
                phrase = line;
	} else if (line.indexOf("|ANTISPAM_KEY|") != -1) {
            line = line.right(line.length() - 14);
            line.replace("\n", "");

            if (line == "")
		keys.append("10");
	    else{
		QList<QString> words = line.split("|");
		words.removeAll("");

		if (!keys.empty())
		    keys.clear();

		keys.append(words);
	    }
        } else if (line.indexOf("|ATTEMPTS|") != -1){
            line = line.right(line.length() - 10);
            line.replace("\n", "");

            bool ok = false;

            if (line == "")
                try_count = 0;
            else
                try_count = line.toInt(&ok, 10);

            if (!ok)
                try_count = 0;
        }
    }

    file.close();
}

void DCAntiSpam::saveSettings() {
    QFile file(QDir::homePath() + "/.eiskaltdc/antispam");

    if (!file.open(QIODevice::WriteOnly))
        return;

    QTextStream out(&file);

    out << "|ANTISPAM_PHRASE|" << phrase << "\n";

    QString words = "";

    for (int i = 0; i < keys.size(); i++)
        words += keys.at(i).toUpper() + "|";

    out << "|ANTISPAM_KEY|" << words << "\n";
    out << "|ATTEMPTS|" << QString().setNum(try_count, 10) << "\n";

    file.close();
}

void DCAntiSpam::setPhrase(QString &phrase) {
    if (phrase == "") {
        this->phrase = (phrase = "5+5=?");
    } else
        this->phrase = phrase;
}

void DCAntiSpam::setKeys(QList<QString> &keys) {
    if (keys.empty())
	return;

    this->keys.clear();
    this->keys.append(keys);
}

QList<QString> DCAntiSpam::getKeys() {
    return keys;
}

QString DCAntiSpam::getPhrase() const {
    return phrase;
}

void DCAntiSpam::clearAll() {
    clearBlack();
    clearGray();
    clearWhite();
}

void DCAntiSpam::clearBlack() {
    black_list.clear();
}

void DCAntiSpam::clearGray() {
    gray_list.clear();
}

void DCAntiSpam::clearWhite() {
    white_list.clear();
}

void DCAntiSpam::SetInstance(DCAntiSpam *aspam) {
    g_pAntiSpam = aspam;
}

DCAntiSpam *DCAntiSpam::Instance() {
    return g_pAntiSpam;
}

void DCAntiSpam::setAttempts(int i){
    try_count = i < 0?try_count:i;
}

int DCAntiSpam::getAttempts() const{
    return try_count;
}
