//******************************************** Включаемые файлы *********************************************

#include "flash_mem.h"
#include "tcp.h"

//******************************************* Локальные константы *******************************************

//******************************************* Проверка параметров *******************************************

//******************************************** Определения типов ********************************************

//************************************ Глобальные (публичные) переменные ************************************

// Указатель на пользовательские настройки
extern fm_user_settings_data_t* fm_user_settings_data;
// Указатель на заводскую информацию
extern fm_factory_mem_data_t* fm_factory_mem_data;
// Указатель на калибровки
extern uint8_t* fm_cbr_data;
// Указатель на общие данные (пользовательскую память)
extern uint8_t* fm_cmn_data;



//************************************* Локальные (приватные) переменные ************************************

//***********************************************************************************************************
//******************************** Определения локальных (приватных) функций ********************************
//***********************************************************************************************************

// Команда записи сетевых настроек
static tcp_resp_errs_t f_cmd_set_eth_config(u32 param, const u8* buf, u32 length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    fun_res_t fun_res = ERR_OK;

    // Проверка размера пакета
    err = (length > sizeof(tcp_eth_cfg_hdr_t)) ? (TCP_ERR_INVALID_CMD_DATA_SIZE) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    tcp_eth_cfg_hdr_t data_hdr;
    memcpy(&data_hdr, buf, length);

    // Формат команды
    switch(param)
    {
        case(LTA_FM_FORMAT_WRITE_SETTINGS):
        {
            // Проверяем текущий пароль, устанавливаем новый
            fun_res = fm_write_user_data(&data_hdr.settings, FM_US_FORMAT_WRITE_ALL, data_hdr.cur_passwd, data_hdr.new_passwd);
        }
        break;

        case(LTA_FM_FORMAT_WRITE_ONLY_FLAGS):
        {
            // Не проверяем текущий пароль, не устанавливаем новый
            fun_res = fm_write_user_data(&data_hdr.settings, FM_US_FORMAT_WRITE_ONLY_FLAGS, data_hdr.cur_passwd, data_hdr.new_passwd);
        }
        break;
        
        case(LTA_FM_FORMAT_ERASE):
        {
            // Проверяем текущий пароль
            fun_res = fm_erase_user_data(data_hdr.cur_passwd);
        }
        break;

        default:
            err = TCP_ERR_INVALID_CMD_PARAMS;
        break;
    }

    // Обработка ошибок
    if (fun_res == ERR_ASSERT_ERROR)
    {
        err = TCP_ERR_CMD_WASNT_EXECUTED;
    }
    else if(fun_res == ERR_RUNTIME_ERROR)
    {
        // Память пуста, а пишут только флаги - это недопустимо
        err = TCP_ERR_INVALID_CMD_PARAMS;
    }
    else if(fun_res == ERR_INVALID_ARGUMENT)
    {
        err = TCP_ERR_INVALID_PASSWORD;
    }

    // TODO - Выполнить перезагрузку МК после отправки ответа

    TCP_EXIT;
    return err;
}


// Команда записи заводских настроек
static tcp_resp_errs_t f_cmd_set_factory_mem(u32 param, const u8* buf, u32 length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    fun_res_t fun_res = ERR_OK;

    // Проверка размера пакета
    err = (length > sizeof(tcp_factory_mem_data_hdr_t)) ? (TCP_ERR_INVALID_CMD_DATA_SIZE) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);
    
    tcp_factory_mem_data_hdr_t data_hdr;
    memcpy(&data_hdr, buf, length);

    // Формат команды
    switch(param)
    {
        case(LTA_FM_FORMAT_WRITE_SETTINGS):
        case(LTA_FM_FORMAT_WRITE_ONLY_FLAGS):
        {
            // Проверяем текущий пароль, устанавливаем новый
            fun_res = fm_write_factory_data(&data_hdr.settings, data_hdr.cur_passwd, data_hdr.new_passwd);
        }
        break;
        
        case(LTA_FM_FORMAT_ERASE):
        {
            // Проверяем текущий пароль
            fun_res = fm_erase_factory_data(data_hdr.cur_passwd);
        }
        break;

        default:
            err = TCP_ERR_INVALID_CMD_PARAMS;
        break;
    }

    // Обработка ошибок
    if (fun_res == ERR_ASSERT_ERROR)
    {
        err = TCP_ERR_CMD_WASNT_EXECUTED;
    }
    else if(fun_res == ERR_RUNTIME_ERROR)
    {
        // Память пуста, а пишут только флаги - это недопустимо
        err = TCP_ERR_INVALID_CMD_PARAMS;
    }
    else if(fun_res == ERR_INVALID_ARGUMENT)
    {
        err = TCP_ERR_INVALID_PASSWORD;
    }

    TCP_EXIT;
    return err;
}


// Команда записи калибровок
static tcp_resp_errs_t f_cmd_write_cbr_data(u32 param, const u8* buf, u32 length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    fun_res_t fun_res = ERR_OK;

    fun_res = fm_write_cbr_data((u8*)buf, param, length);
    
    // Обработка ошибок
    if (fun_res == ERR_ASSERT_ERROR)
    {
        err = TCP_ERR_CMD_WASNT_EXECUTED;
    }

    return err;
}


// Команда очистки калибровок
static tcp_resp_errs_t f_cmd_erase_cbr_data(u32 param, const u8* buf, u32 length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    
    // Размер не более 4 байт
    err = (length > 4) ? (TCP_ERR_INVALID_CMD_PARAMS) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    u16 erase_len = buf[0] | (buf[1] << 8);
    fm_erase_cbr_data(param, erase_len);

    TCP_EXIT;
    return err;
}


// Команда записи общих данных
static tcp_resp_errs_t f_cmd_write_cmn_data(u32 param, const u8* buf, u32 length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    fun_res_t fun_res = ERR_OK;

    fun_res = fm_write_cmn_data((u8*)buf, param, length);
    
    // Обработка ошибок
    if (fun_res == ERR_ASSERT_ERROR)
    {
        err = TCP_ERR_CMD_WASNT_EXECUTED;
    }

    return err;
}


// Команда очистки общих данных
static tcp_resp_errs_t f_cmd_erase_cmn_data(u32 param, const u8* buf, u32 length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    
    // Размер не более 4 байт
    err = (length > 4) ? (TCP_ERR_INVALID_CMD_PARAMS) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    u16 erase_len = buf[0] | (buf[1] << 8);
    fm_erase_cmn_data(param, erase_len);

    TCP_EXIT;
    return err;
}


//--------------------------------------------------

// Команда чтения сетевых настроек
static tcp_resp_errs_t f_cmd_get_eth_config(u32 param, u32 resp_len, u8** buf,  u32* length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    L_UNUSED(param);
    L_UNUSED(resp_len);

    err = (fm_user_settings_data == NULL) ? (TCP_ERR_DATA_IS_EMPTY) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    *buf = (u8*)fm_user_settings_data;
    *length = sizeof(fm_user_settings_data_t);

    TCP_EXIT;
    return err;
}



// Команда чтения заводских настроек
static tcp_resp_errs_t f_cmd_get_factory_mem(u32 param, u32 resp_len, u8** buf,  u32* length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;
    L_UNUSED(param);
    L_UNUSED(resp_len);

    err = (fm_factory_mem_data == NULL) ? (TCP_ERR_DATA_IS_EMPTY) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    *buf = (u8*)fm_factory_mem_data;
    *length = sizeof(fm_factory_mem_data_t);

    TCP_EXIT;
    return err;
}


// Команда чтения калибровок
static tcp_resp_errs_t f_cmd_read_cbr_data(u32 param, u32 resp_len, u8** buf,  u32* length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;

    err = (fm_cbr_data == NULL) ? (TCP_ERR_DATA_IS_EMPTY) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    *buf = (uint8_t*)&fm_cbr_data[param];
    *length = resp_len;

    TCP_EXIT;
    return err;
}



// Команда чтения общих данных
static tcp_resp_errs_t f_cmd_read_cmn_data(u32 param, u32 resp_len, u8** buf,  u32* length)
{
    tcp_resp_errs_t err = TCP_ERR_OK;

    err = (fm_cmn_data == NULL) ? (TCP_ERR_DATA_IS_EMPTY) : (TCP_ERR_OK);
    TCP_CHECK_VAL(err);

    *buf = (uint8_t*)&fm_cmn_data[param];
    *length = resp_len;

    TCP_EXIT;
    return err;
}


//***********************************************************************************************************
//******************************* Определения глобальных (публичных) функций ********************************
//***********************************************************************************************************

// Инициализация команд TCP для текущего модуля
void fm_tcp_init(void)
{
    // RX

    // Команда записи сетевых настроек
    tcp_cmd_set_rx_callback(TCP_CMD_ETH_CFG_SET, f_cmd_set_eth_config);
    
    // Команда записи заводских настроек
    tcp_cmd_set_rx_callback(TCP_CMD_FACTORY_DATA_SET, f_cmd_set_factory_mem);
    
    // Команда записи калибровок
    tcp_cmd_set_rx_callback(TCP_CMD_CBR_DATA_WR, f_cmd_write_cbr_data);
    // Команда очистки калибровок
    tcp_cmd_set_rx_callback(TCP_CMD_CBR_DATA_ER, f_cmd_erase_cbr_data);

    // Команда записи общих данных
    tcp_cmd_set_rx_callback(TCP_CMD_CMN_DATA_WR, f_cmd_write_cmn_data);
    // Команда очистки общих данных
    tcp_cmd_set_rx_callback(TCP_CMD_CMN_DATA_ER, f_cmd_erase_cmn_data);

    // TX

    // Команда чтения сетевых настроек
    tcp_cmd_set_tx_callback(TCP_CMD_ETH_CFG_GET, f_cmd_get_eth_config);

    // Команда чтения заводских настроек
    tcp_cmd_set_tx_callback(TCP_CMD_FACTORY_DATA_GET, f_cmd_get_factory_mem);

    // Команда чтения калибровок
    tcp_cmd_set_tx_callback(TCP_CMD_CBR_DATA_RD, f_cmd_read_cbr_data);

    // Команда чтения общих данных
    tcp_cmd_set_tx_callback(TCP_CMD_CMN_DATA_RD, f_cmd_read_cmn_data);
}



//*********************************************** КОНЕЦ ФАЙЛА ***********************************************
