#include "usbapp/usb_application_temp.h"
#include "usb/usb_bridge.h"
#include "usb/usb_config.h"
#include "usbd_vendor.h"
#include "app/thermo/tsensor.h"
#include "app/thermo/NTCtsensor.h"
#include "app/nfm/nfm_base_excls.h"

#define  PROTO_REQ_GET_TEMPERATURE              0x01   // прочитать усредненную температуру

#define PROTO_REQ_GET_INTERNAL_TEMPERATURE      0x01   // Прочитать внутреннюю температуру устройства
#define PROTO_REQ_GET_EXTERNAL_TEMPERATURE      0x02   // Прочитать внешнюю температуру устройства
#define PROTO_REQ_GET_TEMPERATURE_COEFF         0x03   // Прочитать температурный коэффициент
#define PROTO_REQ_SET_TEMPERATURE_COEFF         0x04   // Записать температурный  коэффициент

static int8_t fThermoAppInit();
static int8_t fThermoAppDeInit();
static void   fThermoAppReset();
static bool   fThermoAppSetup( const tUSBSetupPacket_t * pSetup, bool bFirstStage, bool success );
static size_t fThermoAppControlRx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining );
static size_t fThermoAppControlTx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining );

const sUSBAppEntry_Control_t usbapplication_ACM_planarproto_temp = {

     .fUsbInit     = fThermoAppInit,
     .fUsbDeInit   = fThermoAppDeInit,
     .fUsbSetup    = fThermoAppSetup,
     .fUsbCtlEpRx  = fThermoAppControlRx,
     .fUsbCtlEpTx  = fThermoAppControlTx,
     .fResetEvent  = fThermoAppReset,
};
 
static int8_t fThermoAppInit()
{
    return 0;
}

static int8_t fThermoAppDeInit()
{
    return 0;
}  

static void fThermoAppReset()
{

} 

static bool fThermoAppSetup( const tUSBSetupPacket_t * pSetup, bool bFirstStage, bool success )
{    
    switch ( pSetup->bRequest )
    {
        case PROTO_REQ_GET_TEMPERATURE:
        {    
            switch ( pSetup->wIndex )
            {
                case PROTO_REQ_GET_INTERNAL_TEMPERATURE:
                {
                    #if CONFIG_TSENSOR_EMULATE_FOR_USB
                    return true;
                    #else
                    return ThermoSensor.GetReady();
                    #endif
                }
                break;
                
                case PROTO_REQ_GET_EXTERNAL_TEMPERATURE:
                {
                    return NtcThermoSensor.GetReady();
                }
                break;
                
                case PROTO_REQ_GET_TEMPERATURE_COEFF:
                {
                    return true;
                }
                break;
                
                case PROTO_REQ_SET_TEMPERATURE_COEFF:
                {
                    NFMClass->methods.tempCoefficient.setTempCoeff(pSetup->wValue);
                    return true;
                }
                break;
            }
        }
        break;
    }

    return false;
}

static size_t fThermoAppControlRx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * rx, size_t idx, size_t bytesRemaining )
{
    return 0;
}
  
static size_t fThermoAppControlTx( const tUSBSetupPacket_t * pSetup, sUSBTransfer_t * tx, size_t idx, size_t bytesRemaining )
{
    switch ( pSetup->bRequest )
    {
        case PROTO_REQ_GET_TEMPERATURE:
        {
            switch ( pSetup->wIndex )
            {
                case PROTO_REQ_GET_INTERNAL_TEMPERATURE:
                {
                    tTSensorTemp temp;

                    #if CONFIG_TSENSOR_EMULATE_FOR_USB
                    temp = -1;
                    usb_push_transfer( tx, &temp, sizeof(temp) );
                    #else
                    
                    if( 0 == idx && sizeof(temp) == bytesRemaining )
                    {
                        temp = ThermoSensor.GetTempAVG();
                    
                        usb_push_transfer( tx, &temp, sizeof(temp) );
                    }
                    #endif
                }
                break;
                
                case PROTO_REQ_GET_EXTERNAL_TEMPERATURE:
                {
                    float temp = NFMClass->methods.getAverageExtTemperature();
                    if( 0 == idx && sizeof(temp) == bytesRemaining )
                    {
                        usb_push_transfer( tx, &temp, sizeof(temp) );
                    }
                    return true;
                }
                break;
                
                case PROTO_REQ_GET_TEMPERATURE_COEFF:
                {
                    uint16_t tempCoeff = 0;
                    if( 0 == idx && sizeof(tempCoeff) == bytesRemaining )
                    {
                        NFMClass->methods.tempCoefficient.getTempCoeff(&tempCoeff);
                    
                        usb_push_transfer( tx, &tempCoeff, sizeof(tempCoeff) );
                    }
                    return true;
                }
                break;
                
//                case PROTO_REQ_SET_TEMPERATURE_COEFF:
//                {
//                    NFMClass->methods.tempCoefficient.setTempCoeff(pSetup->wValue);
//                    return true;
//                }
//                break;
            }
        }
        break;
    }

    return usb_count_transfer( tx );
}
 