#include "sertrf.h"

//设置日志打印类型
#define CONFIG_SYS_LOG_LEVEL SYS_LOG_LEVEL_INF
#define SYS_LOG_DOMAIN "Seryrf"

sertrf_t sertrf;

void sertrf_init(void)
{
    uint8_t res = 0;
    res = device_init(&sertrf.device);
    if(res)
    {
        SYS_LOG_WRN("device init error");
    }
    // 打开SYS_LOG打印
    app_cfg_set_sys_log(true);
    // 协议初始化
    Protocol_init(PORT_LINUX_SBDATA, sertrf.device.embedded_device);
    //RGB灯
    work_rgb_led_start();
    //按键初始化
    button_work_init();
    // 协议初始化
    sertrf.resend_read_mutex = xSemaphoreCreateMutex();
    resend_init(&sertrf.resend_device, resend_send, resend_recv, resend_get_length,resend_user_parse);
    // stmisp协议初始化
    stmisp_init(&sertrf.stmisp_device,stmisp_send,stmisp_recv,stmisp_get_length);
    
    //OAT信息获取
    get_partition_status(&sertrf.otau);

    //获取飞控代码地址
    sertrf.fc_address = parse_hex_or_dec(FC_ADDRESS);
    //线程启动
    sertrf_start();
    
    SYS_LOG_INF("sertrf init ok");
}
void sertrf_start(void)
{
    os_thread_create(&sertrf.embedded_thread,
                     "embedded_thread",
                     embedded_thread,
                     NULL,
                     4096,
                     20);
    os_thread_create(&sertrf.pc_thread,
                     "pc_thread",
                     pc_thread,
                     NULL,
                     4096,
                     20);
    os_thread_create(&sertrf.app_thread,
                     "app_thread",
                     app_thread,
                     NULL,
                     4096,
                     15);
    os_thread_create(&sertrf.task_thread,
                     "task_thread",
                     task_thread,
                     NULL,
                     2048,
                     10);
}
void sertrf_rf_switch(uint8_t on)
{
    switch(on)
    {
        case 1:
            rf_start(&sertrf.device);
            break;
        case 0:
            rf_stop(&sertrf.device);
            break;
    }
}
//因为 串口
void embedded_thread(void* arg)
{
    while(true)
    {
        uint32_t embedded_size = embedded_device_get_rx_length(&sertrf.device);
        if(embedded_size > 0)
        {
            uint8_t data[embedded_size ];
            // data[embedded_size] = '\0';
            if(!sertrf.stmisp_device.flag)
                embedded_device_read(&sertrf.device, data, embedded_size,0);

            Protocol_buf_decode(data, embedded_size);
            // SYS_LOG_INF("data : %s", data);
            pc_device_write(&sertrf.device, data, embedded_size);
        }
        // printf_chill_time(10,1000);
        
        //需要添加一些延时，否则会卡死，导致看门狗复位
        // vTaskDelay(( TickType_t ) 1000 / configTICK_RATE_HZ);
        os_thread_sleep(1);
    }
}
void pc_thread(void* arg)
{
    while(true)
    {
        uint32_t pc_size = pc_device_get_rx_length(&sertrf.device);
        
        if(pc_size > 0)
        {
            uint8_t data[pc_size];
            pc_device_read(&sertrf.device, data, pc_size);
            // SYS_LOG_INF("data : %s", data);
            if(!sertrf.stmisp_device.flag)
                embedded_device_write(&sertrf.device, data, pc_size);
        }
        // printf_chill_time(10,1000);
        
        //需要添加一些延时，否则会卡死，导致看门狗复位
        // vTaskDelay(( TickType_t ) 1000 / configTICK_RATE_HZ);
        os_thread_sleep(1);
    }
}
void app_thread(void* arg)
{
    while (true)
    {
        switch(sertrf.resend_device.handle_flag)
        {
            case RESEND_CMD_GET_PARAM:
                sertrf_stauct_t sertrf_stauct;

                strcpy(sertrf_stauct.ble_name, g_cfg_app->device_name_ble);
                strcpy(sertrf_stauct.wifi_ap_ssid, g_cfg_app->app_config_wifi_para.wifi_ap_ssid);
                strcpy(sertrf_stauct.wifi_ap_password, g_cfg_app->app_config_wifi_para.wifi_ap_password);
                strcpy(sertrf_stauct.wifi_sta_ssid, g_cfg_app->app_config_wifi_para.wifi_sta_ssid);
                strcpy(sertrf_stauct.wifi_sta_password, g_cfg_app->app_config_wifi_para.wifi_sta_password);
                
                resend_send_data(&sertrf.resend_device, RESEND_CMD_GET_PARAM, &sertrf_stauct, sizeof(sertrf_stauct_t), 1000);

                sertrf.resend_device.handle_flag = 0;//标志位清零
                break;
            case RESEND_CMD_OTA_GET_PARAM:
                printf("RESEND_CMD_OTA_GET_PARAM\r\n");
                ota_parm_t ota_parm;
                resend_send_data(&sertrf.resend_device, RESEND_CMD_OTA_GET_PARAM, &ota_parm, sizeof(ota_parm_t), 1000);
                sertrf.resend_device.handle_flag = 0;//标志位清零
                break;
            default:
                break;
        }
        resend_recv_data(&sertrf.resend_device, 0);
        // static uint8_t count = 0;
        // count++;
        // if(count > 100)
        // {
        //     // resend_send_cmd(&sertrf.resend_device, RESEND_CMD_ACK, 0);
        //     resend_send_data(&sertrf.resend_device, RESEND_CMD_GET_PARAM, NULL, 0, 0);
        //     // count = 0;
        // }
        // uint32_t app_size = app_device_get_rx_length(&sertrf.device);
        
        // if(app_size > 0)
        // {
        //     uint8_t data[app_size];
        //     app_device_read(&sertrf.device, data, app_size,0);
        //     printf("data:%d:%s\n", app_size,data);
        // }
        os_thread_sleep(1);
    }
    
}
void task_thread(void* arg)
{
    while(true)
    {
        size_t start_time = os_get_sys_time();
        pc_link_rgb_color(&sertrf.device);

        if(sertrf.device.connect_pc > DISCONNECT)
        {
            static size_t end_time = 0;
            if(start_time - end_time > 2000)
            {
                switch(get_protocol_status())
                {
                    case PROTOCOL_STATUS_OK:
                        // rgb_color_change(1, sertrf.device.last_color);
                        rgb_color_change(1, RGB_COLOR_ORANGE);
                        break;
                    case PROTOCOL_STATUS_NO_DATA:
                        rgb_color_change(1, RGB_COLOR_RAD);
                        break;
                    case PROTOCOL_STATUS_TYPE_IDLE:
                        rgb_color_change(1, RGB_COLOR_RAD);
                        break;
                    case PROTOCOL_STATUS_ANALYSIS_ERROR:
                        rgb_color_change(1, RGB_COLOR_RAD);
                        break;
                    case PROTOCOL_STATUS_IN_OTA:
                        rgb_color_change(1, RGB_COLOR_BLUE);
                    default:
                        break;
                }
                end_time = os_get_sys_time();
            }
        }

        os_thread_sleep(100); 
    }
}
void pc_link_rgb_color(device_t* device)
{
    static uint8_t last_connect = 255, last_wifi_mode = 0;
    uint8_t new_color = 0;
    if(device->connect_pc != last_connect || last_wifi_mode != device->init_device.wifi_mode)
    {
        switch (device->connect_pc)
        {
            case DISCONNECT:
            {
                if(device->init_device.wifi_mode == WIFI_NETIF_MODE_AP)
                    new_color = RGB_COLOR_GREEN_WHITE;
                else
                    new_color = RGB_COLOR_GREEN_PURPLE;
                break;
            }    
            case CONNECT_WIFI_TCP:
            {
                if(device->init_device.wifi_mode == WIFI_NETIF_MODE_AP)
                    new_color = RGB_COLOR_WHITE;
                else
                    new_color = RGB_COLOR_PURPLE;

                break;
            }
            case CONNECT_WIFI_UDP:
            {
                if(device->init_device.wifi_mode == WIFI_NETIF_MODE_AP)
                    new_color = RGB_COLOR_WHITE;
                else
                    new_color = RGB_COLOR_PURPLE;

                break;
            }
            case CONNECT_BLE:
            {
                new_color = RGB_COLOR_GREEN;
            }
                break;
            case CONNECT_RF_OFF:
            {
                new_color = RGB_COLOR_BLUE;
            }
                break;
        }

        if(device->last_color != new_color)
            rgb_color_change(0,new_color);

        device->last_color = new_color;

        last_connect = device->connect_pc;
        last_wifi_mode = device->init_device.wifi_mode;

        if(device->connect_pc == DISCONNECT)
        {
            rgb_update_cyle(0,50);
        }
        else if(device->connect_pc){
            rgb_update_cyle(0,888);
        }else{
            rgb_update_cyle(0,500);
        }
    }
}

int resend_send(void* data, uint16_t len, int timeout)
{
    return app_device_write(&sertrf.device, data, len);
}
int resend_recv(void* data, uint16_t len, int timeout)
{
    int ret = 0;
    
    if (xSemaphoreTake(sertrf.resend_read_mutex, portMAX_DELAY) == pdTRUE)
    {
        ret = app_device_read(&sertrf.device, data, len,timeout);
        xSemaphoreGive(sertrf.resend_read_mutex);
    }
    return ret;
}
int resend_get_length(void)
{
    return app_device_get_rx_length(&sertrf.device);
}
void resend_user_parse(void *resend_device) 
{
    resend_device_t* resend_parse = (resend_device_t*)resend_device;
    switch(resend_parse->rx_frame.cmd)
    {
        case RESEND_CMD_SET_PARAM:
            if(sizeof(sertrf_stauct_t) != resend_parse->rx_frame.len)
            {
                printf("RESEND_CMD_SET_PARAM len error\r\n");
            }
            sertrf_stauct_t* sertrf_stauct = (sertrf_stauct_t*)resend_parse->rx_frame.payload;
            
            app_cfg_set_device_name_ble(sertrf_stauct->ble_name, strlen(sertrf_stauct->ble_name));
            app_cfg_set_wifi_ap_ssid(sertrf_stauct->wifi_ap_ssid);
            app_cfg_set_wifi_ap_password(sertrf_stauct->wifi_ap_password);
            app_cfg_set_wifi_sta_ssid(sertrf_stauct->wifi_sta_ssid);
            app_cfg_set_wifi_sta_password(sertrf_stauct->wifi_sta_password);
            resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
            os_thread_sleep(1000);
            esp_restart();
            break;
        case RESEND_CMD_OTA_GET_PARAM:
        {
            if(sizeof(ota_parm_t) != resend_parse->rx_frame.len)
            {
                printf("RESEND_CMD_OTA_GET_PARAM len error\r\n");
            }
            ota_parm_t* ota_parm = (ota_parm_t*)resend_parse->rx_frame.payload;
            printf("RESEND_CMD_OTA_GET_PARAM %d\n", ota_parm->ota_file_size);
            resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
        }
            break;
        case RESEND_CMD_OTA_START:
        {
            //设置协议状态，为了后续灯颜色变化
            protocol_set_message_status(MESSAGE_OTA);
            // if(!sertrf.resend_device.status.resend_flag)
            otau_init(&sertrf.otau);
            resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
        }
            break;
        case RESEND_CMD_OTA_DATA:
        {
            memcpy(sertrf.otau.ota_buff + sertrf.otau.ota_data_cnt, sertrf.resend_device.rx_frame.payload, sertrf.resend_device.rx_frame.len);

            sertrf.otau.ota_data_cnt +=  sertrf.resend_device.rx_frame.len;
            // if(!sertrf.resend_device.status.resend_flag)
            if(sertrf.otau.ota_data_cnt >= 20480 )
            {
                SYS_LOG_DBG("KUYI_CMD_OTA_DATA %d\n", sertrf.resend_device.rx_frame.seq);
                otau_write(&sertrf.otau, sertrf.otau.ota_buff, sertrf.otau.ota_data_cnt);
                sertrf.otau.ota_data_cnt = 0;
            }
            resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
        }
            break;
        case RESEND_CMD_OTA_END:
        {
            if(sertrf.otau.ota_data_cnt > 0)
            {
                otau_write(&sertrf.otau, sertrf.otau.ota_buff, sertrf.otau.ota_data_cnt);
                sertrf.otau.ota_data_cnt = 0;
            }
            // if(!sertrf.resend_device.status.resend_flag)
            otau_end(&sertrf.otau);
            resend_send_cmd(resend_device, RESEND_CMD_ACK, 0);
            os_thread_sleep(2);
            esp_restart();
        }
        break;
    }
}


void Examples_run(void)
{
    //关闭其他线程中相同串口的使用
    sertrf.stmisp_device.flag = 1;
    // 重启飞控，并使其进入isp烧录模式
    fc_reboot();
    boot_set(1);
    os_thread_sleep(1000);
    uart_set_parity_switch(sertrf.device.embedded_device, 0x02);
    os_thread_sleep(100);
    // 与isp确定通讯波特率，并建立联系
    if(!send_sync(&sertrf.stmisp_device, 5))
        printf("stmisp: sync error\n");
    else
        printf("stmisp: sync ok\n");

    os_thread_sleep(100);

    // 解除写保护
    if(!cmd_write_unprotect(&sertrf.stmisp_device))
        printf("stmisp: write unprotect error\n");
    else
        printf("stmisp: write unprotect ok\n");

    os_thread_sleep(100);
    if(!send_sync(&sertrf.stmisp_device, 5))
        printf("stmisp: sync error\n");
    else
        printf("stmisp: sync ok\n");
    os_thread_sleep(100);
    // 全盘擦除
    if(!cmd_extended_erase_mass(&sertrf.stmisp_device))
        printf("stmisp: erase mass error\n");
    else 
        printf("stmisp: erase mass ok\n");

    os_thread_sleep(10);

    printf("stmisp: isp start\n");

}
int stmisp_send(void* data, uint16_t len, int timeout)
{
    return embedded_device_write(&sertrf.device, data, len);
}
int stmisp_recv(void* data, uint16_t len, int timeout)
{
    uint32_t time_start = os_get_sys_time();
    int size = 0;
    while(os_get_sys_time() - time_start < timeout)
    {
        size = embedded_device_read(&sertrf.device, data, len, 0);
        if(size > 0)
            return size;
        os_thread_sleep(1);
    }
    return size;
}
int stmisp_get_length(void)
{
    return embedded_device_get_rx_length(&sertrf.device);
}