//#include <proc/p32mx440f256h.h>

#include "LoraInterface.h"
#include "BoardCfg.h"
#include "timer.h"
#include "NetworkInterface.h"
#include "ProtocolDefs.h"
#include "Uart.h"



short mModuleModel;


int InitLoraInterface()
{
    mModuleModel = LORA_MODULE_MODEL;
    InitLoraModule();
    SetLoraModuleTxMode();
    LoraResetRxStateMachine();
    
    LoraInterfaceRequestModuleConfig();
    
  	return RET_OK;
}

int LoraInterfaceRxData(char Data)
{
    LoraRxStateMachine(Data,LORA_RX_SM_NEW_DATA_EVENT);
    return RET_OK;
}

//Analyze data coming from lora module COM port
int LoraRxStateMachine(char Data, int Event)
{
    switch(mLoraRxSMState)
    {
        case LORA_RX_SM_STANBY_STATE:
        {
            switch(Event)
            {
                case LORA_RX_SM_NEW_DATA_EVENT:
                {
                    mLoraModuleBuffer[mBufferIndex++] = Data;
                    mLoraRxSMState = LORA_RX_SM_RECEIVING_STATE;
                    TimerStart(LORA_MODULE_COMM_TIMER,LORA_RX_INTERBYTE_TIMEOUT);
                    break;
                }
                case LORA_RX_SM_TICK_EVENT:
                {
                    break;
                }
            }
            break;
        }
        case LORA_RX_SM_RECEIVING_STATE:    //Receiving wireless data from remote device
        {
            switch(Event)
            {
                case LORA_RX_SM_NEW_DATA_EVENT:
                {
                    mLoraModuleBuffer[mBufferIndex++] = Data;
                    TimerStart(LORA_MODULE_COMM_TIMER,LORA_RX_INTERBYTE_TIMEOUT);
                    if(mBufferIndex >= MAX_LORA_BUFFER_SIZE)
                    {
                        //TODO: Manage the exception with the MasterCtrl.
                        LoraResetRxStateMachine();
                    }
                    break;
                }
                case LORA_RX_SM_TICK_EVENT:
                {
                    if(IsTimerExpired(LORA_MODULE_COMM_TIMER))
                    {
                        SendNetworkCommand(LORA_IF_NEW_FRAME_RESPONSE,mLoraModuleBuffer,mBufferIndex);
                        LoraResetRxStateMachine();
                        LoraInterfaceRequestModuleRSSI(); 
                    }
                    break;
                }
            }
            break;
        }
        case LORA_RX_SM_CONFIG_STATE:   //we are waiting for answer from module command
        {
            switch(Event)
            {
                case LORA_RX_SM_NEW_DATA_EVENT:
                {
                    mLoraModuleBuffer[mBufferIndex++] = Data;
                    TimerStart(LORA_MODULE_COMM_TIMER,LORA_RX_INTERBYTE_TIMEOUT);
                    if(mBufferIndex >= MAX_LORA_BUFFER_SIZE)
                    {
                        //TODO: Manage the exception with the MasterCtrl.
                        LoraResetRxStateMachine();
                    }
                    break;
                }
                case LORA_RX_SM_TICK_EVENT:
                {
                    if(IsTimerExpired(LORA_MODULE_COMM_TIMER))
                    {
                        switch(mLastConfigCommand)
                        {
                            case LORA_CONFIG_READ_CONFIG_CMD:
                            {
                                SetLoraModuleTxMode();
                                AnalyzeLoraModuleConfigData(mLoraModuleBuffer,mBufferIndex);
                                break;
                            }
                            case LORA_CONFIG_READ_RSSI_CMD:
                            {
                                AnalyzeLoraModuleRSSI(mLoraModuleBuffer,mBufferIndex);
                            }
                        }
                        LoraResetRxStateMachine();
                    }
                    break;
                }
            }
            break;
        }
    }
    return RET_OK;
}

void LoraResetRxStateMachine()
{
    mLoraRxSMState = LORA_RX_SM_STANBY_STATE;
    mBufferIndex = 0;
}

int LoraInterfaceTransmitLoRaData(char *Payload, unsigned int PayloadSize)
{
    if(mLoraRxSMState != LORA_RX_SM_STANBY_STATE)
    {
        //TODO: Manage this...
        
        return LORA_IF_RET_BUSY_CHANNEL;
    }
    
    SendInternalUartDataBlocking(Payload,PayloadSize,LORA_MODULE_UART_PORT);
    TimerStart(LORA_MODULE_COMM_TIMER,LORA_RX_INTERBYTE_TIMEOUT);
    
    return LORA_IF_RET_OK;
}

void LoraInterfaceTick()
{
    LoraRxStateMachine(0,LORA_RX_SM_TICK_EVENT);
}

void LoraInterfaceRequestModuleConfig()
{
    mLoraRxSMState = LORA_RX_SM_CONFIG_STATE;
    ReadLoraModuleConfig();
    mLastConfigCommand = LORA_CONFIG_READ_CONFIG_CMD;
    TimerStart(LORA_MODULE_COMM_TIMER,LORA_RX_INTERBYTE_TIMEOUT);
}
void LoraInterfaceRequestModuleRSSI()
{
    mLoraRxSMState = LORA_RX_SM_CONFIG_STATE;
    ReadLoraModuleRSSI();
    mLastConfigCommand = LORA_CONFIG_READ_RSSI_CMD;
    TimerStart(LORA_MODULE_COMM_TIMER,LORA_RX_INTERBYTE_TIMEOUT);
}

int LoraInterfaceIsBusy()
{
    if(mLoraRxSMState != LORA_RX_SM_STANBY_STATE)
    {
        return 1;
    }
    return 0;
}