#ifndef NETWORKMANAGER_H
#define NETWORKMANAGER_H

#include <QObject>
#include "GlobalDefine.h"
#include "ZTData.h"
#include <QTcpSocket>
#include <QUdpSocket>
#include "TCPProtocol.h"
#include "UDPProtocol.h"

class COutilZT;

class CNetworkManager : public QObject, public CTCPProtocol, public CUDPProtocol
{
    Q_OBJECT
public:

    enum eZTNetworkStatus
    {
        ZT_NETWORK_OFFLINE_STATUS,
        ZT_NETWORK_ONLINE_STATUS,
        ZT_NETWORK_SEARCHING_STATUS,
        ZT_NETWORK_UNKNOWN_STATUS,
        ZT_NETWORK_CONNECTED_STATUS
    };

    static CNetworkManager* instance(){return &mSingleton;}
    static  CNetworkManager mSingleton;

    explicit CNetworkManager(QObject *parent = 0);
    ~CNetworkManager();

    void BindPointers(COutilZT *ProgramHandle);
    unsigned int SetConfig(CSettingsData *Config);
    unsigned int ConnectToZT(int ZTID);
    unsigned int DisconnectZT();
    unsigned int RefreshRemoteZTStatus();
    unsigned int DownloadZTLog();
    unsigned int DownloadTrainLogs();
    unsigned int DeleteRemoteZTLog();
    unsigned int SetZTFunctions(const CTCPZTFunctionsStatus &ZTFunctions);

    unsigned int InitUDPConnection(int ZTID);
    unsigned int StopUDPStream();
    unsigned int CloseUDPConnection();

    int CheckZTConnectionsStatus();

    virtual void TCPTxRequest(const QByteArray &request);
    virtual void TCPRxHeartbeat();
    virtual void TCPRxStationName(QString Name);
    virtual void TCPRxZTStatus(const QByteArray &data);
    virtual void TCPRxZTLog(QString ZTLog);
    virtual void TCPRxTrainLogsDownladAck(qint32 NbFiles);
    virtual void TCPRxTrainLogFileData(const QByteArray &TrainFileData);
    virtual void TCPRxTrainLogsDownloadFinished();
    virtual void TCPRxDeleteZTLogAck(bool success);
    virtual void TCPRxSetZTFunctionsAck(bool ack);

private:
    typedef enum
    {
        NETWORK_SM_INIT_STATE,
        NETWORK_SM_STANDBY_STATE,
        NETWORK_SM_INITIATE_CLIENT_CONNECTION_STATE,
        NETWORK_SM_CLIENT_CONNECTED_STATE

    }eNetworkSMState;

    typedef enum
    {
        NETWORK_ONLINE_CHK_SM_INIT_STATE,
        NETWORK_ONLINE_CHK_SM_STANDBY_STATE,
        NETWORK_ONLINE_CHK_SM_CHECK_CONNECTIONS_STATE
    }eNetworkOnlineCheckSMState;

    typedef enum
    {
        NETWORK_SM_TIMER_EVENT,
        NETWORK_SM_SOCKET_CONNECTED_EVENT,
        NETWORK_SM_SOCKET_DISCONNECTED_EVENT,
        NETWORK_SM_DATA_RX_EVENT,
        NETWORK_SM_DATA_SEND_EVENT,
        NETWORK_SM_SOCKET_ERROR_EVENT
    }eNetworkSMEvent;

    void NetworkStateMachine(eNetworkSMEvent event);
    void OnlineCheckStateMachine(eNetworkSMEvent event);

    QTcpSocket mZTTcpSocket;
    QTcpSocket mZTOnlineCheckingSocket;
    QUdpSocket *mZTUDPSocket;
    QHostAddress mUDPServerAdress;
    CSettingsData *mConfig;
    eNetworkSMState mNetworkSMState;
    eNetworkOnlineCheckSMState mOnlineCheckNetworkSMState;


    int mCurZTID;
    int mOnlineCheckZTID;
    COutilZT *mProgramHandle;


    
signals:
    void NetworkZTConnectionStatus(int,int);
    void NetworkZTConnected(int);
    void NetworkZTDisconnected(int);
    void NetworkZTConnectionError(int);
    void NetworkTCPTx();
    void NetworkTCPRx();

public slots:

    void SocketConnected();
    void SocketDisconnected();
    void SocketError(QAbstractSocket::SocketError socketError);
    void SocketDataReady();
    void OnlineCheckSocketError(QAbstractSocket::SocketError socketError);
    void OnlineCheckSocketConnected();

    void UDPSocketDataReady();
    
};

#endif // NETWORKMANAGER_H
