#include "multithreadserver.h"

MultiThreadServer::MultiThreadServer(ServerLMSWidget *widget,UpdateController *updateController,ProcessingSystem *processingSystem,
    DataParser *dataParser,qint16 hostPort, QObject *parent ):
    QTcpServer(parent),
    serverLmsWidget(widget),
    hostPort(hostPort),
    processingSystem(processingSystem),
    updateController(updateController),
    dataParser(dataParser),
    stateServer(stoped),
    stateBlockAutorization(blocked)
{
    clientsMap = new QMap<int,ClientHandler*>;
}

void MultiThreadServer::incomingConnection(qintptr socketDesriptor)
{
    ClientHandler* newClient = new ClientHandler;

    connect(this,&MultiThreadServer::sigInitClient,newClient,&ClientHandler::initialize,Qt::AutoConnection);
    connect(newClient,&ClientHandler::sigClientDisconnected,this,&MultiThreadServer::slotDisconnectClient,Qt::AutoConnection);
    emit sigInitClient(socketDesriptor,serverLmsWidget,updateController,dataParser);
    disconnect(this,&MultiThreadServer::sigInitClient,newClient,&ClientHandler::initialize);

    addClient(socketDesriptor,newClient);

    Logger::instance().log("To Client: " + QString(SERVER_HELLO));
}

bool MultiThreadServer::startServer()
{
    if(stateServer == stoped)
    {
        //connect(tcpServer, &QTcpServer::newConnection, this, &ServerLMSWidget::slotNewConnection,Qt::AutoConnection);

        if(!listen(QHostAddress::Any, hostPort))
        {
            Logger::instance().log("SERVER: start ERROR");
            stateServer = stoped;
            return false;
        }
        else
        {
            Logger::instance().log("SERVER: start OK");
            stateServer = started;
            return true;
        }
    }
    else
        return false;
}

bool MultiThreadServer::stopServer()
{
    if(stateServer == started)
    {
        disableClients();

        //Закрываем сервер
        close();
        stateServer = stoped;
        Logger::instance().log("SERVER: stop OK");
        return true;
    }
    else
        return false;
}

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

void MultiThreadServer::updateClientList()
{
    serverLmsWidget->slot_UpdateListClients();
}

void MultiThreadServer::disableClients()
{
     QByteArray arrayAnswer = dataParser->ClientAnswer()->notify(NOTIFY_SERVER_END);

    //Закрываем все открытые сокеты
    foreach(int idSocket, clientsMap->keys())
    {
        ClientHandler* handler = (*clientsMap)[idSocket];

        //Фиксируем время выхода Юнити-клиента
        if(handler->getClient()->getClientType()  == TypeClientAutorization::TYPE_UNITY_CLIENT)
        {
            processingSystem->processingExitUnityClient(handler);
        }

        handler->sigSendXmlAnswer(arrayAnswer, PacketType::TYPE_XMLANSWER);
        QString str = QString(arrayAnswer);
        processingSystem->processingClientDeAutorization(handler->getClient()->getLogin());

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

}

void MultiThreadServer::slotDisconnectClient(QString peerAddress, QString peerPort)
{
    QString login = "";
    qDebug() << peerAddress << " " << peerPort << " " << "disconnect";

    //Проходим все открытые сокеты, ищем нужный
    foreach(int idSocket, clientsMap->keys())
    {
        ClientHandler *client = (*clientsMap)[idSocket];

        if(client->getClient()->getAddress() == peerAddress && client->getClient()->getPort() == peerPort)
        {
            login = client->getClient()->getLogin();

            ClientDeAutorization clientDeAutorization;
            clientDeAutorization.Login = login;
            processingSystem->processingClientDeAutorization(client, clientDeAutorization);

            removeClient(idSocket);
            delete client;
            continue;
        }

    }

    emit signalStopSendFile();
    Logger::instance().log("SERVER: Client " + login + " disconnected");

    serverLmsWidget->slot_UpdateListClients();
    serverLmsWidget->getProcessingSystem()->processingClientDeAutorization(login);
}

void MultiThreadServer::removeClient(int idSocket)
{
    clientsMap->remove(idSocket);
    serverLmsWidget->slot_UpdateListClients();
}

void MultiThreadServer::addClient(qintptr descriptor, ClientHandler *client)
{
    (*clientsMap)[descriptor] = client;
    serverLmsWidget->slot_UpdateListClients();
}

