#include "dcipfilter.h"

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

const QString signature = "$EISKALTDC IPFILTERLIST$";

DCIPFilter *g_pIPFilter;

DCIPFilter::DCIPFilter()
{
    role = eMATCH;

    basic_ip = new QRegExp("^(\\d{1,3}.){3,3}\\d{1,3}$");

    g_pIPFilter = this;
}

DCIPFilter::~DCIPFilter()
{
    delete basic_ip;

    g_pIPFilter = NULL;
}

void DCIPFilter::setRole(eREGEXP_ROLE role)
{
#ifdef _DEBUG_
    qDebug() << "SET ROLE: " << role;
#endif
    this->role = role;
}

eREGEXP_ROLE DCIPFilter::getRole() const
{
#ifdef _DEBUG_
    qDebug() << "GET ROLE: " << role;
#endif
    return role;
}

void DCIPFilter::addToRules(QString exp, eDIRECTION direction)
{
    if (list.contains(exp)){
        if (list[exp] != direction){
            emit ruleChanged(exp, direction, eDIRECTION_BOTH);

            list[exp] = eDIRECTION_BOTH;
        }

        return;
    }
    else
        list[exp] = direction;

    emit ruleAdded(exp, list[exp]);
}

void DCIPFilter::remFromRules(QString exp)
{
    if (list.contains(exp)){
        emit ruleRemoved(exp, list[exp]);

        list.remove(exp);
    }
}

bool DCIPFilter::OK(QString exp, eDIRECTION direction)
{
    bool found = false;

    QHash<QString, eDIRECTION>::const_iterator i = list.constBegin();

    while (i != list.constEnd()){
        QString str_exp = i.key();
        QRegExp reg_exp(str_exp);

        if (reg_exp.exactMatch(exp)){
            if (i.value() == eDIRECTION_BOTH ||
                i.value() == direction){
                found = true;
            }
            else{
                found = false;
            }


            break;
        }
        ++i;
    }

    if (found){
        switch (role){
            case eMATCH:
                return true;
                break;
            case eNOMATCH:
                return false;
                break;
        }
    }
    else{
        switch (role){
            case eMATCH:
                return false;
                break;
            case eNOMATCH:
                return true;
                break;
        }
    }

    return false;
}

bool DCIPFilter::isIP(QString &exp)
{
    return basic_ip->exactMatch(exp);
}

void DCIPFilter::loadList()
{
    QFile file(QDir::homePath()+"/.eiskaltdc/ipfilter");

    if (!file.exists())
        return;

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

    if (!list.empty())
	clearRules();

    QTextStream in(&file);

    while (!in.atEnd()){
        QString pattern = in.readLine();
        eDIRECTION direction = eDIRECTION_IN;

        if (pattern.indexOf("|D_IN|:") == 0)
            pattern = pattern.right(pattern.length()-7);
        else if (pattern.indexOf("|D_OUT|:") == 0){
            pattern = pattern.right(pattern.length()-8);
            direction = eDIRECTION_OUT;
        }
        else if (pattern.indexOf("|D_BOTH|:") == 0){
            pattern = pattern.right(pattern.length()-9);
            direction = eDIRECTION_BOTH;
        }
	else if (pattern == "|MATCH|"){
	    setRole(eMATCH);
	    continue;
	}
	else if (pattern == "|NOMATCH|"){
	    setRole(eNOMATCH);
	    continue;
	}
	else
	    continue;

        pattern.replace("\n", ""); pattern.replace(" ", "");
        addToRules(pattern, direction);
    }

    file.close();
}

void DCIPFilter::saveList()
{
    QFile file(QDir::homePath()+"/.eiskaltdc/ipfilter");

    if (list.empty()){
	file.remove();
	return;
    }

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

    QTextStream out(&file);

    out << signature << "\n";

    QHash<QString, eDIRECTION>::const_iterator i = list.constBegin();

    while (i != list.constEnd()){
        QString prefix = "|D_IN|:";
        QString exp = i.key();

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

        eDIRECTION direction = i.value();

        switch (direction){
            case eDIRECTION_BOTH:
                prefix = "|D_BOTH|:";

                break;
            case eDIRECTION_OUT:
                prefix = "|D_OUT|:";

                break;
            default:
                break;
        }

        out << prefix+exp+"\n";

        ++i;
    }

    QString param = "|MATCH|";

    switch (role){
	case eNOMATCH:
	    param = "|NOMATCH|";

	    break;
	 default:
	    break;
     }

     param += "\n";

     out << param;

     file.close();
}

void DCIPFilter::exportTo(QString path)
{
    QFile file(QDir::homePath()+"/.eiskaltdc/ipfilter");
    QMessageBox msgBox;

    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    msgBox.setIcon(QMessageBox::Warning);

    saveList();

    if (!file.exists()){
	msgBox.setText(tr("Nothing to export."));
	msgBox.exec();

	return;
    }

    QFile exp_file(path);

    if (exp_file.exists())
	exp_file.remove();

    if (!file.copy(path)){
	msgBox.setText(tr("Unable to export settings."));
	msgBox.exec();

	return;
    }
}

void DCIPFilter::importFrom(QString path)
{
    QFile file(path);
    QMessageBox msgBox;

    msgBox.setStandardButtons(QMessageBox::Ok);
    msgBox.setDefaultButton(QMessageBox::Ok);
    msgBox.setIcon(QMessageBox::Warning);

    if (!file.exists() || !file.open(QIODevice::ReadOnly|QIODevice::Text)){
	msgBox.setText(tr("Nothing to import."));
	msgBox.exec();
	file.close();

	return;
    }

    QTextStream in(&file);
    QString sign = in.readLine();

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

    file.close();

    if (sign == signature){
	QFile old_file(QDir::homePath()+"/.eiskaltdc/ipfilter");
	old_file.remove();

	file.copy(QDir::homePath()+"/.eiskaltdc/ipfilter");
	loadList();
    }
    else{
	msgBox.setText(tr("Invalid signature."));
	msgBox.exec();
    }
}

void DCIPFilter::changeRuleDirection(QString exp, eDIRECTION direction)
{
    if (list.contains(exp) && list[exp] != direction){
	emit ruleChanged(exp, list[exp], direction);

	list[exp] = direction;
    }
}

void DCIPFilter::getRules(QHash<QString, eDIRECTION> &list)
{
    list = this->list;
}

void DCIPFilter::clearRules()
{
   QHash<QString, eDIRECTION> list;

   getRules(list);
   
   QHash<QString, eDIRECTION>::const_iterator i = list.constBegin();

   while (i != list.constEnd()){
       remFromRules(i.key());
       ++i;
   }
}

#ifdef _DEBUG_
void DCIPFilter::printHash()
{
    QHash<QString, eDIRECTION>::const_iterator i = list.constBegin();

    while (i != list.constEnd()){
        qDebug() << "Hash: {KEY: " << i.key() << ", VALUE: " << i.value() << "}";

        ++i;
    }
}
#endif

