#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSettings>
#include <QHostAddress>
#include <QMessageBox>
#include <QDebug>
#include "dialogshowvariable.h"
#include "protocol/RemoteServer.h"
#include "protocol/RemoteServerController.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    curContext(NULL),
    eventListener(new MyEventListener())
{
    ui->setupUi(this);
    QApplication::setApplicationName("AggreGate Util");
    QApplication::setOrganizationName("Tibbo");

    QSettings settings;
    ui->edIP->setText(settings.value("IP", "127.0.0.1").toString());
    ui->edLogin->setText(settings.value("Login", "admin").toString());
    ui->edPassword->setText(settings.value("Password", "admin").toString());

    connect(ui->tbConnect, SIGNAL(clicked()), SLOT(onConnect()));
    connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
                            SLOT(onCurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)));
    connect(ui->listVariables, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(onVariableDoubleClicked(QListWidgetItem*)));
    connect(ui->listEvents, SIGNAL(itemDoubleClicked(QListWidgetItem*)), SLOT(onEventDoubleClicked(QListWidgetItem*)));
    connect(eventListener.get(), SIGNAL(addLogText(QString)), SLOT(onAddLogText(QString)));
}

MainWindow::~MainWindow()
{
    QSettings settings;
    settings.setValue("IP", ui->edIP->text());
    settings.setValue("Login", ui->edLogin->text());
    settings.setValue("Password", ui->edPassword->text());

    if (rlc != NULL)
    {
        rlc->disconnect();
    }

    delete ui;
}

std::list<ContextInfo> getChildContexts(Context *context)
{
    std::list<ContextInfo> res;
    std::list<Context*> list = context->getVisibleChildren();


    return res;
}

void MainWindow::onConnect()
{
    if (ui->tbConnect->text() == "Connect")
    {
        QHostAddress myIP;
        if( myIP.setAddress(ui->edIP->text()) )
        {
            try
            {
                rls = RemoteServerPtr( new RemoteServer(ui->edIP->text().toStdString(), RemoteServer::DEFAULT_PORT(),
                                                    ui->edLogin->text().toStdString(), ui->edPassword->text().toStdString(),false));
                rlc = RemoteServerControllerPtr( new RemoteServerController(rls.get(), false) );
                rlc->connect();
                rlc->login();

                ContextManager* cm = rlc->getContextManager();
                Context* rootContext = cm->getRoot();

                QTreeWidgetItem *rootItem = new QTreeWidgetItem();
                //QString text = toQString(rootContext->getDescription());
                AgString str = rootContext->getDescription();
                rootItem->setText(0, toQString(str));
                rootItem->setData(0, Qt::UserRole, qVariantFromValue((void *) rootContext));
                ui->treeWidget->addTopLevelItem(rootItem);

                addChildContexts(rootItem, rootContext);
            }
            catch (AggreGateException ex)
            {
                AgString str1 = ex.getMessage();
                QMessageBox::information(this, "AggreGate Util", toQString(str1));
                return;
            }

            ui->tbConnect->setText("Disconnect");
            ui->edIP->setEnabled(false);
            ui->edLogin->setEnabled(false);
            ui->edPassword->setEnabled(false);
            ui->label->setEnabled(false);
            ui->label_2->setEnabled(false);
            ui->label_3->setEnabled(false);
        }
        else
        {
            QMessageBox::information(this, "AggreGate Util", "Invalid IP address");
        }
    }
    else
    {
        for (QMap<EventDefinitionPtr, Context*>::iterator it = subscibedEvents.begin(); it != subscibedEvents.end(); ++it)
        {
            it.value()->removeEventListener(it.key()->getName(), boost::dynamic_pointer_cast<ContextEventListener>(eventListener));
        }
        subscibedEvents.clear();

        rlc->disconnect();
        ui->listVariables->clear();
        ui->listEvents->clear();
        ui->treeWidget->clear();
        ui->edLog->clear();
        rlc = RemoteServerControllerPtr();
        rls = RemoteServerPtr();
        ui->tbConnect->setText("Connect");
        ui->edIP->setEnabled(true);
        ui->edLogin->setEnabled(true);
        ui->edPassword->setEnabled(true);
        ui->label->setEnabled(true);
        ui->label_2->setEnabled(true);
        ui->label_3->setEnabled(true);
    }
}

void MainWindow::onCurrentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
    UNUSED(previous);
    if (current)
    {
        void *v = current->data(0, Qt::UserRole).value<void *>();
        curContext = (Context *)v;

        ui->listVariables->clear();
        ui->listEvents->clear();

        std::list<VariableDefinitionPtr> vars  = curContext->getVariableDefinitions();
        for (std::list<VariableDefinitionPtr>::iterator var = vars.begin(); var != vars.end(); ++var)
        {
            QListWidgetItem *item = new QListWidgetItem(toQString((*var)->getName()));
            ui->listVariables->addItem(item);
        }

        std::list<EventDefinitionPtr> events  = curContext->getEventDefinitions();
        for (std::list<EventDefinitionPtr>::iterator event = events.begin(); event != events.end(); ++event)
        {
            QListWidgetItem *item = new QListWidgetItem(toQString((*event)->getName()));
            if (subscibedEvents.find(*event) != subscibedEvents.end())
            {
                item->setTextColor(QColor(0, 155, 0));
            }
            else
            {
                item->setTextColor(QColor(0, 0, 0));
            }

            ui->listEvents->addItem(item);
        }

        //updated event
       EventDefinitionPtr updatedEvent = curContext->getEventDefinition("updated");
       if (updatedEvent)
       {

            QListWidgetItem *item = new QListWidgetItem("updated");
            if (subscibedEvents.find(updatedEvent) != subscibedEvents.end())
            {
                item->setTextColor(QColor(0, 155, 0));
            }
            else
            {
                item->setTextColor(QColor(0, 0, 0));
            }

            ui->listEvents->addItem(item);
       }
    }
}

void MainWindow::onVariableDoubleClicked(QListWidgetItem * item)
{
    if (curContext && item)
    {
        DataTablePtr dt = curContext->getVariable(item->text().toStdString());
        DialogShowVariable dlg(this);
        dlg.setWindowTitle(item->text());

        AgString str = dt->toString();
        dlg.setText(toQString(str));
        dlg.exec();
    }
}

void MainWindow::onEventDoubleClicked(QListWidgetItem *item)
{
    if (curContext && item)
    {
        EventDefinitionPtr event = curContext->getEventDefinition(item->text().toStdString());

        //unsubscribe
        if (subscibedEvents.find(event) != subscibedEvents.end())
        {
            if (!curContext->removeEventListener(item->text().toStdString(), boost::dynamic_pointer_cast<ContextEventListener>(eventListener)))
            {
                QMessageBox::information(this, "AggreGate Util", "function removeEventListener return false");

            }
            else
            {
                subscibedEvents.remove(event);
                item->setTextColor(QColor(0, 0, 0));
            }
        }
        //subscribe
        else
        {
            if (!curContext->addEventListener(item->text().toStdString(), boost::dynamic_pointer_cast<ContextEventListener>(eventListener)))
            {
                QMessageBox::information(this, "AggreGate Util", "function addEventListener return false");

            }
            else
            {
                subscibedEvents[event] = curContext;
                item->setTextColor(QColor(0, 155, 0));
            }
        }

    }
}

void MainWindow::onAddLogText(const QString &text)
{
    ui->edLog->appendPlainText(text);
}

QString MainWindow::toQString(AgString &str)
{
    return QString::fromUtf8(str.toUtf8().c_str());
}

void MainWindow::addChildContexts(QTreeWidgetItem *item, Context* context)
{
    std::list<Context*> list = context->getVisibleChildren();
    for (std::list<Context*>::iterator it = list.begin(); it != list.end(); ++it)
    {
        QTreeWidgetItem *childItem = new QTreeWidgetItem();
        AgString mes = (*it)->getDescription();
        childItem->setText(0, toQString(mes));
        childItem->setData(0, Qt::UserRole, qVariantFromValue((void *) *it));
        item->addChild(childItem);

        AgString sss = (*it)->getPath();
        qDebug() << toQString(sss);

        addChildContexts(childItem, *it);
    }
}

void MyEventListener::handle(EventPtr event)
{
    AgString mes = event->getName();
    QString name = MainWindow::toQString(mes);
    AgDatePtr date = event->getInstantiationtime();
    boost::posix_time::ptime t = date->getValue();
    std::string sss = boost::posix_time::to_simple_string(t);
    DataTablePtr dt = event->getData();
    if (dt)
    {
        AgString mes = dt->toString();
        name = "[" + QString::fromStdString(sss) + "]   " + name +  " : " + MainWindow::toQString(mes);
    }
    emit addLogText(name);
}
