#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QXmlStreamAttribute>
#include <QFile>
#include <QMessageBox>
#include <QThread>


#include "serverlmswidget.h"
#include "ui_serverlmswidget.h"

//#include "instructorsAndTrainees.h"
#include "instructorsandtraineeswidget.h"


ServerLMSWidget::ServerLMSWidget(InstructorsAndTraineesWidget* instructorsAndTrainees, MessangerWidget* messangerWidget, QWidget *parent) :
    QWidget(parent),
    tcpServer(nullptr),
    hostPort(6000),
    stateServer(stoped),
    stateBlockAutorization(/*unblocked*/blocked),
    pInstructorsAndTrainees(instructorsAndTrainees),
    pMessangerWidget(messangerWidget),
    ui(new Ui::ServerLMSWidget)
{
    ui->setupUi(this);

    ui->btnStopServer->setEnabled(false);
    ui->btnStartServer->setEnabled(true);

    // Сделаем первоначальную инициализацию перевода для окна виджета
    qtLanguageTranslator.load(QString("translations/ServerLMS_") + QString("ru_RU"), ".");
    qApp->installTranslator(&qtLanguageTranslator);

    updateThread = new QThread;
    loggerThread = new QThread;

    ui->comboTasks->addItem("Задача 1");
    ui->comboTasks->addItem("Задача 2");
    ui->comboTasks->addItem("Задача 3");
    ui->comboTasks->addItem("Задача 4");
    ui->comboTasks->addItem("Задача 5");

    logger = new Logger(ui->listWidgetLogger);
    connect(logger,&Logger::sigSendTextToLogger,this,&ServerLMSWidget::slotAddToLog,Qt::QueuedConnection);
    logger->moveToThread(loggerThread);


    processingSystem = new ProcessingSystem;
    dataParser = new DataParser(processingSystem);

    updateController = new UpdateController;
    updateController->moveToThread(updateThread);

    loggerThread->start();
    updateThread->start();

    updateController->initialize(nullptr,dataParser);
    processingSystem->initialize(dataParser,this,instructorsAndTrainees);

    logger->setTypeLog("widget");

    //connect(processingSystem,&ProcessingSystem::sigAuthChanged,this,&ServerLMSWidget::signal_authorizationChanged); //Уже не требуется!
    connect(processingSystem,&ProcessingSystem::sigUpdateListClients,this, &ServerLMSWidget::slotUpdateListClients);
    connect(pMessangerWidget, &MessangerWidget::signal_msgToClientReady, this, &ServerLMSWidget::slot_msgToClientReady);

    connect(updateController,&UpdateController::sigLogMessage,logger,&Logger::addTextToLogger);
    connect(dataParser,&DataParser::sigLogMessage,logger,&Logger::addTextToLogger);
    connect(processingSystem,&ProcessingSystem::sigLogMessage,logger,&Logger::addTextToLogger);
    connect(processingSystem,&ProcessingSystem::sigAddToMessanger,this,&ServerLMSWidget::slotAddToMessanger,Qt::QueuedConnection);
    connect(this,&ServerLMSWidget::sigLog,logger,&Logger::addTextToLogger);

    on_btnStartServer_clicked();

    first = true;
    qDebug() << "WidgetThread: " << QThread::currentThreadId();
}

void ServerLMSWidget::autorizationHandler(QString login)
{
    //Отмена авторизации в БД

    if(pInstructorsAndTrainees->deAuthorizationTrainee(login))
    {//Деавторизовался обучаемый

    }
    else  if(pInstructorsAndTrainees->deAuthorizationInstructor(login))
    {//Деавторизовался инструктор

    }

    //Извещаем об изменениях в авторизации ??? не нашел, где он вызывает изменения
    //emit signal_authorizationChanged(); //Уже не требуется!
}

ServerLMSWidget::~ServerLMSWidget()
{
    stopServer();
    updateThread->exit();
    loggerThread->exit();
    delete ui;
}

bool ServerLMSWidget::startServer()
{
    if(stateServer == stoped)
    {
        tcpServer = new MultiThreadServer(this,updateController,dataParser,logger);

        //connect(tcpServer, &QTcpServer::newConnection, this, &ServerLMSWidget::slotNewConnection,Qt::AutoConnection);

        if(!tcpServer->listen(QHostAddress::Any, hostPort))
        {
            logger->addTextToLogger("SERVER: start ERROR");
            stateServer = stoped;
            return false;
        }
        else
        {
            logger->addTextToLogger("SERVER: start OK");
            stateServer = started;
            return true;
        }
    }
    else
        return false;
}

bool ServerLMSWidget::stopServer()
{
    if(stateServer == started)
    {
        QByteArray arrayAnswer = dataParser->xmlAnswer_notify(NOTIFY_SERVER_END);

        //Закрываем все открытые сокеты
        foreach(int idSocket, clientsMap.keys())
        {
            clientsMap[idSocket]->sigSocketWrite(arrayAnswer);
            //while (!clientsMap[idSocket]->sigSocketFlush()) {}

            QString str = QString(arrayAnswer);
            emit sigLog("To Client: " + str);

            //slotDisconnectClient(clientsMap[idSocket]->get, QString peerPort)
            autorizationHandler(clientsMap[idSocket]->getClient()->getLogin());

            clientsMap[idSocket]->sigSocketClose();
            //clientsMap.remove(idSocket);
            removeClient(idSocket);
        }

        //Закрываем сервер
        tcpServer->close();
        stateServer = stoped;
        delete tcpServer;
        emit sigLog("Server is stopped");
        return true;
    }
    else
        return false;
}

QMap<int, ClientHandler *> ServerLMSWidget::getClientsMap() const
{
    return clientsMap;
}

void ServerLMSWidget::slotUpdateListClients()
{
    //Очищаем список
    ui->listWidget_Clients->clear();

    //Проходим все открытые сокеты
    foreach(int idSocket, clientsMap.keys())
    {
        //Добавляем в список Клиентов
        QString strClient = clientsMap[idSocket]->getClient()->getFullName();

        ui->listWidget_Clients->addItem(strClient);
        ui->listWidget_Clients->scrollToBottom();
        ui->listWidget_Clients->setCurrentRow(ui->listWidget_Clients->count() - 1);
    }

    int countClients = clientsMap.count();
    logger->addTextToLogger("SERVER: countClients = " + QString::number(countClients));
}

void ServerLMSWidget::slot_BlockAutorization(bool block)
{
    if(block)
        blockAutorization();
    else
        unBlockAutorization();
}

void ServerLMSWidget::slotAddToMessanger(QString login, QString text)
{
    QString name = pInstructorsAndTrainees->getNameTraineeByLogin(login);
    pMessangerWidget->addMsg(login, name, text, MessangerWidget::ETypeMsg::fromClient);
}

void ServerLMSWidget::removeClient(int idSocket)
{
    clientsMap.remove(idSocket);
    slotUpdateListClients();
}

void ServerLMSWidget::addClient(qintptr descriptor, ClientHandler *client)
{
    clientsMap[descriptor] = client;
    slotUpdateListClients();
}

void ServerLMSWidget::slot_LanguageChanged(QString language)
{
    qtLanguageTranslator.load(QString("translations/ServerLMS_") + language, ".");
    qApp->installTranslator(&qtLanguageTranslator);
}


void ServerLMSWidget::slot_msgToClientReady(QString login, QString text)
{
    QString textMsg = text;

    QByteArray byteArrayMsg = dataParser->xmlAnswer_message(textMsg);

    //Проходим все открытые сокеты, ищем нужный
    foreach(int idSocket, clientsMap.keys())
    {
        ClientHandler *handler = clientsMap[idSocket];
        if(handler->getClient()->getLogin() == login)
        {//Отправляем ему

            handler->sendXmlAnswer(byteArrayMsg);

            QString peerAddress = clientsMap[idSocket]->getSocket()->peerAddress().toString();
            QString peerPort = QString::number(clientsMap[idSocket]->getSocket()->peerPort());

            QString str = "Msg To Client [" + peerAddress + ":" + peerPort + "] : " + textMsg;

            logger->addTextToLogger(str);      
            break;
        }
    }
}

void ServerLMSWidget::slotAddToLog(QString msg)
{
    ui->listWidgetLogger->addItem(msg);
    ui->listWidgetLogger->scrollToBottom();
}


void ServerLMSWidget::on_btnStartServer_clicked()
{
    if(startServer())
    {
        QApplication::setOverrideCursor(Qt::WaitCursor);
        updateController->calculateHash();
        QApplication::restoreOverrideCursor();

        ui->btnStartServer->setEnabled(false);
        ui->btnStopServer->setEnabled(true);
        ui->lblOnOff->setPixmap(QPixmap(QStringLiteral(":/icons/switchOn.png")));
    }
}

void ServerLMSWidget::on_btnStopServer_clicked()
{
    if(stopServer())
    {
        ui->btnStopServer->setEnabled(false);
        ui->btnStartServer->setEnabled(true);
        ui->lblOnOff->setPixmap(QPixmap(QStringLiteral(":/icons/switchOff.png")));
    }
}

void ServerLMSWidget::on_btnTaskSet_clicked()
{
    QString fullNameClient = ui->listWidget_Clients->currentItem()->text();

    QString textTask = ui->comboTasks->currentText();

    QByteArray byteArrayTask = dataParser->xmlAnswer_task(textTask);

    //Проходим все открытые сокеты
    foreach(int idSocket, clientsMap.keys())
    {
        if(clientsMap[idSocket]->getClient()->getFullName() == fullNameClient)
        {//Отправляем ему
            clientsMap[idSocket]->getSocket()->write(byteArrayTask);

            QString peerAddress = clientsMap[idSocket]->getSocket()->peerAddress().toString();
            QString peerPort = QString::number(clientsMap[idSocket]->getSocket()->peerPort());

            QString str = "Task To Client [" + peerAddress + ":" + peerPort + "] : " + textTask;
            logger->addTextToLogger(str);
        }
    }
}

void ServerLMSWidget::changeEvent(QEvent *event)
{
    // В случае получения события изменения языка приложения
    if (event->type() == QEvent::LanguageChange)
    {
        ui->retranslateUi(this);    // переведём окно заново
    }
}

