#ifndef COMMUNICATIONS_H
#define COMMUNICATIONS_H

#include <QObject>
#include <QThread>
#include <QSerialPort>
#include <QTcpSocket>
#include <QUdpSocket>
#include <QHostAddress>
#include <QMutex>
#include <QDebug>

#define QDEBUG(x)        (qDebug() <<__FUNCTION__ <<x)

class ProcotolBase : public QObject
{
    Q_OBJECT
public:
    explicit ProcotolBase(QObject *parent = 0)
        : QObject(parent)
    {
    }

    ~ProcotolBase(){
    }
    virtual bool setFrameData(QByteArray&);

    QByteArray getByteArray(){
        return(contentByteArray);
    }
    quint32 getTypeId(){
        return(typeId);
    }

public:
    quint32 typeId;
    QByteArray contentByteArray;
};

class CommunicationBase : public QThread
{
    Q_OBJECT
public:
    explicit CommunicationBase(QObject *parent = 0): QThread(parent) {}
    virtual bool open() {return true;}
    virtual void close();
    virtual bool send(const QByteArray&) ;
    virtual void run();

private:
    virtual void processFrameData(){}
    virtual bool forwardMsg(const QByteArray&);
    virtual bool uploadServerMsg(const QByteArray&);

signals:
    void emitForwardMsg(const QByteArray&);
    void emitUploadServerMsg(const QByteArray&);
    void emitSaveLocalMsg(const QByteArray&);

public slots:
    virtual void forwardMsgSlot(const QByteArray&);
    virtual void uploadServerMsgSlot(const QByteArray&);
    virtual void received() {}
    virtual void restart();

protected:
    QMutex forwardMutex;
    QMutex uploadMutex;
    QByteArray rcvByteArray;
    QList<QByteArray> forwardByteArrayList;
    QList<QByteArray> uploadByteArrayList;
};

class CommunicationSerialPort : public CommunicationBase
{
    Q_OBJECT
public:
    explicit CommunicationSerialPort(const QString &name,
                                     QSerialPort::BaudRate baud =QSerialPort::Baud115200,
                                     QObject *parent = 0);
    ~CommunicationSerialPort();
    virtual bool open();
    virtual void close();
    virtual bool send(const QByteArray&);
    void modify(const QString &name, QSerialPort::BaudRate baud);
    QSerialPort *getSerialPort();
signals:

public slots:
    QByteArray readAll();

private:
    QString portName;
    QSerialPort::BaudRate m_baud;
    QSerialPort* m_serialPort;
};

class CommunicationTcpSocket : public CommunicationBase
{
    Q_OBJECT
public:
    explicit CommunicationTcpSocket(const QString &hostIpAddress,
                                     quint16 port,
                                     QObject *parent = 0);
    ~CommunicationTcpSocket();
    virtual bool open();
    virtual void close();
    virtual bool send(const QByteArray&);
    void modify(const QString &hostIpAddress, quint16 port);

signals:

public slots:
    virtual void received();
    void disconnected();

private:
    QTcpSocket* m_tcpSocket;
    QHostAddress peekAddress;
    quint16 peekPort;
};

class CommunicationUdpSocket : public CommunicationBase
{
    Q_OBJECT
public:
    explicit CommunicationUdpSocket(const QString &hostIpAddress,
                                     quint16 port,
                                     QObject *parent = 0);
    ~CommunicationUdpSocket();
    virtual bool open();
    virtual void close();
    virtual bool send(const QByteArray&);
    void modify(const QString &hostIpAddress, quint16 port);

signals:

public slots:

private:
    QUdpSocket* m_udpSocket;
    QHostAddress peekAddress;
    quint16 peekPort;
};

#endif // COMMUNICATIONS_H
