#include "LoraModuleInterface.h"
#include <QDataStream>


CLoraModuleInterface::CLoraModuleInterface()
{
    connect(&mLoraModuleIFSerialPort,SIGNAL(readyRead()),this,SLOT(NewLoraModuleIFDataReady()));

    mLoraModuleIFStatusTimer = new QTimer();
    mLoraModuleIFStatusTimer->setSingleShot(false);
    mLoraModuleIFStatusTimer->setInterval(1000);
    mLoraModuleIFStatusTimer->start();

    mLoraDeviceCommSurrogate = new CNetworkCommIFSurrogate;
    mLoraDeviceCommSurrogate->mMyNetworkAddress = 1;
    mLoraDeviceCommSurrogate->mMyNetworkID = ID_MASTER;
    connect(mLoraDeviceCommSurrogate,&CNetworkCommIFSurrogate::ValidFrameReady,this,&CLoraModuleInterface::LoraRemoteDeviceDataReceived);



    connect(mLoraModuleIFStatusTimer,&QTimer::timeout,this,&CLoraModuleInterface::LoraModuleStatusTimerExpired);

}

CLoraModuleInterface::~CLoraModuleInterface()
{
    delete mLoraModuleIFStatusTimer;
    delete mLoraDeviceCommSurrogate;
}


//This the handling of the Microcontroller (LoraModuleInterface)
int CLoraModuleInterface::NewFrameReceived(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray Data)
{
    switch(MessageID)
    {
        case LORA_IF_GET_STATUS_RESPONSE:
        {
            QDataStream Strm(Data);
            Strm >> mLoraModuleStatus;
            qDebug("Lora device status received");

            break;
        }
        case LORA_IF_SEND_FRAME_RESPONSE:
        {
            qDebug("LoraModuleInterface sent frame to end Lora device");
            break;
        }
        case LORA_IF_NEW_FRAME_RESPONSE:    //LoraInterface received a message from the Lora end point (chalet for example).  Let's decode it and send it to the destination device
        {

            //Use the surrogate to analyse the buffer.  When frame is complete it will trigger a signal.
            mLoraDeviceCommSurrogate->AnalyzeRxBuffer(Data);

//            CNetworkProtocol *mTempProtocol = new CNetworkProtocol;   //Let's instanciate a temp protocol class to avoid messing with our own derived class...
//            int FwdDeviceID;
//            int FwdDeviceAddress;
//            int FwdMessageID;
//            int FwdDataSize;
//            QByteArray FwdData;
//            if(mTempProtocol->ProtocolAnalyseBufferStatically(Data,FwdDeviceID,FwdDeviceAddress,FwdMessageID,FwdDataSize,FwdData) == PROTOCOL_RET_OK_PACKET_COMPLETE)
//            {
//                mDevicePtr->NewDeviceFrameReceived(FwdDeviceID,FwdDeviceAddress,FwdMessageID,FwdDataSize,FwdData);
//            }
//            else
//            {
//                qDebug("LoraModuleInterface received an invalid packet from end Lora device in NewFrameReceived");
//            }

//            delete mTempProtocol;

            break;
        }
        case LORA_IF_GET_MODULE_CONFIG_RESPONSE:
        {
            break;
        }
        case LORA_IF_GET_RSSI_RESPONSE:
        {
            break;
        }
        case LORA_IF_SET_MODULE_CONFIG_RESPONSE:
        {
            break;
        }
        case LORA_IF_GET_STATUS_REQUEST:
        case LORA_IF_SEND_FRAME_REQUEST:
        case LORA_IF_GET_MODULE_CONFIG_REQUEST:
        case LORA_IF_GET_RSSI_REQUEST:
        case LORA_IF_SET_MODULE_CONFIG_REQUEST:
        default:
        {
            qDebug("CLoraModuleInterface: Received invalid response from LoraModule: %d",MessageID);
            break;
        }

    }

    return RET_OK;
}

//This is the CAbstractNetworkCommIF class implementation (to answer to CChaletDevice requests).
int CLoraModuleInterface::SendNetworkMessage(int DeviceID, int DeviceAddress, int MessageID, int DataSize, QByteArray *Data)
{
    qDebug("LoraInterfce: New frame received from MasterCtrl class");


    //Get the payload by building the Msg packet
    QByteArray Payload = GetTxPacket(MessageID,0,Data->data(),DataSize,DeviceAddress,DeviceID);

    //Prepend the destination lora address & channel
    Payload.prepend(mLoraPreamble);
//    Payload.prepend(mDestLoraAddress);
//    Payload.prepend((char)(mDestLoraChannel &0x00FF));
//    Payload.prepend((char)((mDestLoraAddress >>8)));

    //Now get the packet to communicate with LoraInterface uC
    QByteArray Packet = GetTxPacket(LORA_IF_SEND_FRAME_REQUEST,0,Payload,Payload.size(),1,ID_LORA_INTERFACE_DEVICE);
    mLoraModuleIFSerialPort.write(Packet);
    mLoraModuleIFSerialPort.waitForBytesWritten(500);
    return RET_OK;
}



void CLoraModuleInterface::LoraModuleStatusTimerExpired()
{
    QByteArray Packet = GetTxPacket(LORA_IF_GET_STATUS_REQUEST,0,0,0,1,ID_LORA_INTERFACE_DEVICE);
    mLoraModuleIFSerialPort.write(Packet);
    mLoraModuleIFSerialPort.waitForBytesWritten(500);
}

int CLoraModuleInterface::SetLoraModuleInterfaceParameters(QString ComPort, qint32 BaudRate)
{
    mLoraModuleIFComPortName = ComPort;
    mLoraModuleIFComPortBaudRate = BaudRate;


    if(mLoraModuleIFSerialPort.isOpen())
    {
        mLoraModuleIFSerialPort.close();
    }

    mLoraModuleIFSerialPort.setPortName(mLoraModuleIFComPortName);
    if(mLoraModuleIFSerialPort.setBaudRate(mLoraModuleIFComPortBaudRate) == false)
    {
        qDebug("Invalid Lora Device serial port baud rate...");
    }

    //The other serial port parameters (parity, stop bits, data bits) are all set to mentally sane default values so no need to set them.
    if(mLoraModuleIFSerialPort.open(QIODevice::ReadWrite) == false)
    {
        qDebug("Could not open Lora device port");
        return RET_ERROR;
    }

    qDebug("LoraModuleInterface serial port opened");
    return RET_OK;



    return RET_OK;
}

int CLoraModuleInterface::SetLoraDestinationAddress(quint16 Address, quint8 Channel)
{
    mDestLoraAddress = Address;
    mDestLoraChannel = Channel;
    mLoraPreamble.clear();
    mLoraPreamble.append(mDestLoraChannel);
    mLoraPreamble.prepend((char)(mDestLoraAddress &0x00FF));
    mLoraPreamble.prepend((char)((mDestLoraAddress >>8)));
    return RET_OK;
}

void CLoraModuleInterface::NewLoraModuleIFDataReady()
{
    QByteArray NewData = mLoraModuleIFSerialPort.readAll();

    AnalyzeRxBuffer(NewData);
}

void CLoraModuleInterface::LoraRemoteDeviceDataReceived(int FwdDeviceID, int FwdDeviceAddress, int FwdMessageID, int FwdDataSize, QByteArray FwdData)
{
    //Multiple devices could be connected to the interface.  Find the sender
    //NOTE: This needs a major rework of the inheritance scheme!

    QObject *SenderObj = QObject::sender();
    if(SenderObj == mLoraDeviceCommSurrogate)
    {
        mDevicePtr->NewDeviceFrameReceived(FwdDeviceID,FwdDeviceAddress,FwdMessageID,FwdDataSize,FwdData);
    }
}

void CLoraModuleInterface::LoraRemoteDeviceReceiveError(CNetworkProtocol::ProtocolRetValues RetID)
{

}
