#include "gbuilder.h"
#include <QDir>
#include <QDebug>
#include <QDomDocument>
#include <iostream>
#include <QTabWidget>
#include <QLayout>
#include <QVBoxLayout>
#include <QMapIterator>
#include <QGroupBox>
#include <QToolBox>
#include <QFormLayout>
#include <QLabel>
#include "tools/checkboxswitcher.h"
#include "tools/fileswitcher.h"
#include "tools/listswitcher.h"
#include "tools/pairsswitcher.h"
#include "tools/selectswitcher.h"
#include "tools/textswitcher.h"
#include "tools/switcher.h"
#include "mainwindow.h"

GBuilder::GBuilder(MainWindow *mw): tools()
{
    mainWindow = mw;
}

GBuilder::~GBuilder() {
    for (int i = 0; i < tools.size(); i++) {
        delete tools.at(i);
    }

    delete tabWidget;
}

void GBuilder::loadTools() {
    //QDir dir(QDir::homePath() + "/" + APP_DIR + "/" + TOOLS_DIR);
    QDir dir(QString(APP_DIR) + "/" + TOOLS_DIR);

    if (!dir.exists())
     qWarning() << "Cannot find the tools directory - " << dir.absolutePath();

    dir.setFilter(QDir::Files);
    dir.setSorting(QDir::Name);

     QFileInfoList list = dir.entryInfoList();
     for (int i = 0; i < list.size(); ++i) {
         QFileInfo fileInfo = list.at(i);
         try {
            tools.append(loadTool(fileInfo.absoluteFilePath()));
        } catch (QString e) {
            qWarning() << e;
        }
     }

}

Tool* GBuilder::loadTool(QString path) {
    QFile file(path);
    QDomDocument doc(file.fileName());

        if (!doc.setContent(&file)) {
            file.close();
            throw "Error while opening file ocured - " + file.fileName();
        }

        Tool* tool = new Tool();;
        QMap <QString, QList<Switcher*> >groupContains;
        QDomElement docElem = doc.documentElement();
        QDomNode node = docElem.firstChild();

        tool->setName(docElem.attribute("name"));
        tool->setProcess(docElem.attribute("type") == "info" ? false:true);

        while(!node.isNull()) {
            QDomElement element = node.toElement(); // try to convert the node to an element.
            if (!element.isNull()) {
                if(element.tagName() == "command"){
                    tool->setCommand(element.text());
                }
                else if(element.tagName() == "info"){
                    tool->setInfo(element.text());
                }
                else if(element.tagName() == "homepage"){
                    tool->setHomepage(element.text());
                }
                else if(element.tagName() == "options"){
                    QDomNodeList groupList = docElem.elementsByTagName("group");
                    for (int i = 0; i <  groupList.size(); i++) {
                        QList<Switcher*> switcherList;
                        QDomElement groupElement =  groupList.at(i).toElement();
                        QString groupName = groupElement.attribute("name");
                        if (!groupList.at(i).isNull()) {
                            QDomNode switcherNode = groupList.at(i).firstChild();
                            while(!switcherNode.isNull()) {
                                   QDomElement switcherElement = switcherNode.toElement();

                                   Switcher *switcher;
                                   if (switcherElement.nodeName() == "checkbox"){
                                        switcher = new CheckboxSwitcher;
                                   } else if (switcherElement.nodeName() == "file"){
                                        switcher = new FileSwitcher;
                                   } else if (switcherElement.nodeName() == "text"){
                                       switcher = new TextSwitcher;
                                   } else if (switcherElement.nodeName() == "pairs"){
                                       switcher = new PairsSwitcher;
                                   } else if (switcherElement.nodeName() == "select"){
                                       switcher = new SelectSwitcher;
                                   } else if (switcherElement.nodeName() == "list"){
                                       switcher = new ListSwitcher;
                                   }

                                   if (!switcherElement.isNull()) {
                                       switcher->setValuesFromNode(switcherElement);
                                   }

                                   switcherList.push_back(switcher);
                                   switcherNode = switcherNode.nextSibling();
                              }
                        }
                    tool->getGroupsOrder().push_back(groupName);
                    groupContains.insert(groupName,switcherList);
                    }
                }
            }
            node = node.nextSibling();
        }
    tool->setGroups(groupContains);
    return tool;
}



void GBuilder::build(QWidget *w) {
    loadTools();

    tabWidget = new QTabWidget(w);
    tabWidget->setObjectName(QString::fromUtf8("tabWidget"));
    tabWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);

    for (int i = 0; i < tools.size(); i++) {
        Tool* tool = tools.at(i);
        QString name = tool->getName();
        QToolBox *tab = new QToolBox();
        tab->setObjectName("tab_" + name);
        tabWidget->addTab(tab, name);

         QListIterator<QString> it(tool->getGroupsOrder());
         while (it.hasNext()) {
             QString groupName = it.next();
             QList<Switcher*> p = tool->getGroups().value(groupName);
             QWidget *g = new QWidget(tab);
             QFormLayout *formLayout = new QFormLayout(g);
             formLayout->setSpacing(6);
             formLayout->setContentsMargins(11, 11, 11, 11);
             formLayout->setObjectName(QString::fromUtf8("formLayout"));
             for( int j = 0; j < p.size(); j++){
                 Switcher *switcher = p.at(j);
                 QObject::connect(switcher, SIGNAL(change()),
                                  mainWindow, SLOT(on_switcher_value_changed()));
                 QWidget *comp = switcher->getComponent(g);
                 QLabel *lab = new QLabel(switcher->getName());

                 if (switcher->isRequired()) lab->setStyleSheet("font-weight: bold");

                 lab->setToolTip(switcher->getInfo());
                 formLayout->setWidget(j, QFormLayout::LabelRole, lab);
                 if (comp != 0) formLayout->setWidget(j, QFormLayout::FieldRole, comp);
             }
             tab->addItem(g, groupName);
         }
    }
    w->layout()->addWidget(tabWidget);
}


void GBuilder::saveProject(QString filename) {
    Tool* t = getSelectedTool();

    QDomDocument xml;
    xml.setContent(QString("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"), false);
    QDomElement root = xml.createElement("project");

    root.setAttribute("tool", t->getName());

    QMapIterator<QString, QList<Switcher*> > it(t->getGroups());
    while (it.hasNext()) {
        it.next();
        QString groupName = it.key();
        QListIterator<Switcher*> sit(it.value());

        QDomElement group = xml.createElement("group");
        group.setAttribute("name", groupName);

        while (sit.hasNext()) {
            Switcher* switcher = sit.next();
            QDomElement e = xml.createElement("switcher");
            group.appendChild(switcher->getProjectNode(e));
        }

        root.appendChild(group);
    }

    xml.appendChild(root);
    QFile out(filename);
    out.open(QIODevice::WriteOnly);
    QTextStream stream(&out);
    xml.save(stream, 0);
    out.close();

}


void GBuilder::openProject(QString filename) {
    QFile file(filename);
    QDomDocument doc(file.fileName());

    if (!doc.setContent(&file)) {
        file.close();
        throw "Error while opening file ocured - " + file.fileName();
    }

    QDomElement root = doc.elementsByTagName("project").at(0).toElement();
    QString toolName = root.attribute("tool");

    Tool* tool = 0;
    for (int i = 0; i < tools.size(); i++) {
        if (tools.at(i)->getName() == toolName) {
            tool = tools.at(i);
            tabWidget->setCurrentIndex(i);
            break;
        }
    }

    if (tool == 0) {
        qWarning() << "Cannot find tool with name - " << toolName;
        return;
    }

    QDomNode node = root.firstChild();
    while(!node.isNull()) {
        QDomElement element = node.toElement(); // try to convert the node to an element.
        if (element.isNull()) continue;

        QString groupName = element.attribute("name");

        QDomNodeList switchers = element.childNodes();
        for (int i = 0; i < switchers.size(); i++) {
            QDomElement el = switchers.at(i).toElement();
            QList<Switcher*> ss = tool->getGroups().value(groupName);

            for (int j = 0; j < ss.size(); j++) {
                Switcher* s = ss.at(j);
                if (s->getName() == el.attribute("name") && s->getSwitcher() == el.attribute("switcher"))
                    s->setSavedValues(el);
            }
        }

        node = node.nextSibling();
    }
}
