/*******************************************************************************
*                                                                              *
* Société de Transports de Montréal.                                    	   *
* 2015                                                                         *
*                                                                              *
* Projet Zones Tests                                                           *
*                                                                              *
*                                                                              *
*                                                                              *
*******************************************************************************/
/*
    Description:
    Classe qui gère la communication IP entre la Zone Test et l'outil d'analyse.

*/

/* ************************************************************************** */
/* Revision:
### 20121210 JFM
    Verision d'origine.

### YYYYMMDD Description du besoin ou du bug
    Description du changement.
 */

/* ************************************************************************** */

#include "NetworkManager.h"
#include <QDebug>
#include <QByteArray>
#include <Zonetest.h>
#include <ZTLog.h>


CNetworkManager CNetworkManager::mSingleton;

CNetworkManager::CNetworkManager(QObject *parent) :
    QObject(parent)
{
    mProgramHandle = 0;
    mTCPSocket = 0;
    mCurTrainLogsListIndex = 0;
    mTrainLogsFileInfoList.clear();


    connect(&mTCPServer,SIGNAL(newConnection()),this,SLOT(NewTCPConnection()));
}

CNetworkManager::~CNetworkManager()
{
    mTCPSocket->disconnectFromHost();
    mTCPServer.close();
}

void CNetworkManager::BindPointers(CZoneTest *ProgramHandle)
{
    mProgramHandle = ProgramHandle;
}

unsigned int CNetworkManager::StartServer()
{
    if(mTCPServer.listen(QHostAddress::Any,TCP_SERVER_PORT) == false)
    {
        CZTLog::instance()->AddLogString("Impossible de démarrer le serveur TCP",true);
        return RET_ERROR;
    }

    CZTLog::instance()->AddLogString(QString().sprintf("Serveur TCP démarré sur le port %d",TCP_SERVER_PORT),true);
    return RET_OK;

}

void CNetworkManager::NewTCPConnection()
{
    mTCPSocket = mTCPServer.nextPendingConnection();

    if(mTCPSocket == 0)
    {
        CEngLog::instance()->AddLogString("Invalid socket from TCP server");
        return;
    }

   // mTCPSocket->setSocketOption(QAbstractSocket::LowDelayOption,1);

    connect(mTCPSocket,SIGNAL(readyRead()),this,SLOT(TCPDataReady()));
    connect(mTCPSocket,SIGNAL(disconnected()),this,SLOT(TCPSockedDisconnected()));

    QString str = "Client connecté : ";
    str += mTCPSocket->peerAddress().toString();
    CZTLog::instance()->AddLogString(str,true);
}

void CNetworkManager::TCPDataReady()
{
    qint64 datasize = mTCPSocket->bytesAvailable();
    //QByteArray data= mTCPSocket->read(datasize);

    qDebug() << "TCP data received" << datasize;// << "bytes: " << data.toHex();

    AnalyzeNewData(mTCPSocket->readAll());

}

void CNetworkManager::TCPSockedDisconnected()
{
    CZTLog::instance()->AddLogString("Client TCP déconnecté",true);
    //StartServer();
}

void CNetworkManager::TCPTxRequest(QByteArray request)
{
    qDebug() << "Tx request in Network Manager : " << request.size() << " bytes : " << request.toHex();

    mTCPSocket->write(request);
}

void CNetworkManager::TCPHeartbeatRequest()
{
    qDebug("TCP: Received heartbeat request...");
    mTCPSocket->write(GetHeartbeatPacket());
}

void CNetworkManager::TCPStationNameRequest()
{
    qDebug("TCP: Received station name request...");
    mTCPSocket->write(GetStationNamePacket(mProgramHandle->GetStationTextualName()));
}

void CNetworkManager::TCPStatusRequest()
{
    qDebug("TCP: Received ZT status request");
    CTCPZTStatus *status = mProgramHandle->GetTCPStatusRequest();
    mTCPSocket->write(GetZTStatusPacket(status));
    delete status;
//    mTCPSocket->write(SendZTStatus());
}

void CNetworkManager::TCPZTLogDownloadRequest()
{
    qDebug("TCP: Received ZTLog Download request");
    QString *ZTLogText = mProgramHandle->GetZTLogTextRequest();
    mTCPSocket->write(GetZTLogPacket(ZTLogText));
    delete ZTLogText;
}

void CNetworkManager::TCPTrainLogsDownloadRequest()
{
    mTrainLogsFileInfoList.clear();
    mTrainLogsFileInfoList = mProgramHandle->GetTrainLogsFileListRequest();
    mCurTrainLogsListIndex = 0;

    //Add LogZT.txt to the list of files to transfer...
    mTrainLogsFileInfoList.append(QFileInfo("./LOG/LogZT.txt"));

    mTCPSocket->write(GetTrainLogsDownloadAckPacket((qint32)mTrainLogsFileInfoList.size()));

}

void CNetworkManager::TCPTrainLogFileDataAck(eTCPProtocolAcknowledge Acknowledge)
{
    if(mCurTrainLogsListIndex >= mTrainLogsFileInfoList.size())
    {
        mTCPSocket->write(GetTrainLogsDownloadFinishedPacket());
        return;
    }

    if(Acknowledge != TCP_PROTOCOL_ACK)
    {
        //TODO: Manage NACK codes...
        return;
    }

    //Send next file

    QByteArray FileData;
    QDataStream strm(&FileData,QIODevice::WriteOnly);
    strm.device()->seek(0);

    QFile* BinaryLogFile = new QFile(mTrainLogsFileInfoList.at(mCurTrainLogsListIndex).absoluteFilePath());
    if(BinaryLogFile)
    {
        if(BinaryLogFile->open(QIODevice::ReadOnly | QIODevice::Unbuffered) == false)
        {
            delete BinaryLogFile;
            return;
        }

    }
    else
    {
        return;
    }

    strm << mTrainLogsFileInfoList.at(mCurTrainLogsListIndex).fileName();

    FileData.append(BinaryLogFile->readAll());
    BinaryLogFile->flush();
    BinaryLogFile->close();
    delete BinaryLogFile;

    QByteArray *Packet = GetTrainLogDataPacket(FileData);

    qDebug() << "Sending: " << mTrainLogsFileInfoList.at(mCurTrainLogsListIndex).absoluteFilePath();
    mTCPSocket->write(*Packet);

    delete Packet;
    mCurTrainLogsListIndex++;
}

void CNetworkManager::TCPDeleteZTLogRequest()
{
    qDebug("TCP: Received ZTLog Delete request");
    if(mProgramHandle->DeleteZTLogRequest() == RET_OK)
    {
        mTCPSocket->write(GetDeleteZTLogsAckPacket((qint32)TCP_PROTOCOL_ACK));
    }
    else
    {
        mTCPSocket->write(GetDeleteZTLogsAckPacket((qint32)TCP_PROTOCOL_NACK));
    }
}

void CNetworkManager::TCPSetZTFunctionsConfigRequest(QByteArray &Data)
{
    qDebug("TCP: Received Set ZT functions config request");

    CTCPZTFunctionsStatus FunctionsConfig;
    QDataStream strm(&Data,QIODevice::ReadOnly);
    strm.device()->seek(0);

    strm >> FunctionsConfig;

    if(mProgramHandle->SetZTFunctionsConfig(FunctionsConfig) == RET_OK)
    {
        mTCPSocket->write(GetSetZTFunctionsConfigAckPacket((qint32)TCP_PROTOCOL_ACK));
    }
    else
    {
        mTCPSocket->write(GetSetZTFunctionsConfigAckPacket((qint32)TCP_PROTOCOL_NACK));
    }
}






