#include "app_Ble_User.h"
#include "gatts_table_creat_demo.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"
#include "MCU_Core_Protocol.h"
#include "Protocol_User.h"
#include "main_user.h"
#include "esp_log.h"
#include "Protocol_User.h"

#define TAG "APP_BLE_USER"


app_Ble_Time_Info_Struct BleTime;
app_Ble_User_Data_Union BleRecData;
app_Ble_User_Data_Union BleTransData;
app_Ble_Rec_Data_Ctrl_Struct RecCtrl;

uint8_t Wifi_OTA_Request = 0;

uint8_t ble_key[32]   =  "1BJ7J8S";
uint8_t ble_uerid[32] =  {0};
uint8_t ble_pwd[32]   =  {0};
uint8_t flavor[4]   =  {0x33, 0, 0, 0};


SemaphoreHandle_t BleRecSuc_Semaphore;




Ble_User_Control_Struct Ble_User;
Ble_Navi_Info_Struct Ble_Navi_Data;


uint8_t Char_To_Dec(uint8_t input, uint8_t *output)
{
    uint8_t i = 0;
    if(input < '0' || input >'9')
    {
        return 0;
    }

    *output = input - 0x30;

    return 1;
}

uint8_t tp_Ble_Crc(uint8_t *data, uint32_t len )
{
    uint8_t val = 0;

    for(uint32_t i = 0; i<len; i++)
    {
        val ^= data[i];
    }

    return val;
}

void Ble_Clear_Rx_Buffer(void )
{
    for(int i = 0; i< sizeof(BleRecData.Data); i++)
    {
        BleRecData.Data[i] = 0;
    }
}

void Ble_Clear_Tx_Buffer(void )
{
    for(int i = 0; i< sizeof(BleTransData.Data); i++)
    {
        BleTransData.Data[i] = 0;
    }
}



/**************************************************************************/

/**************************************************************************/

uint8_t Ble_Get_User_Info(void )
{
    uint8_t i = 0;
    uint8_t ret = 0;
    // for(i = 24; i<32;i++)
    // {
    //     ble_uerid[i] = 0x30+i-24;
    //     ble_pwd[i] = 0x30+i-24;
    // }

    // ble_uerid[0] = 'v';
    // ble_uerid[1] = 'i';
    // ble_uerid[2] = 'v';
    // ble_uerid[3] = 'a';
    // ble_uerid[4] = 'v';
    // ble_uerid[5] = 'i';
    // ble_uerid[6] = 'v';
    // ble_uerid[7] = 'a';
    // ble_uerid[8] = 'v';
    // ble_uerid[9] = 'i';
    // ble_uerid[10] = 'v';
    // ble_uerid[11] = 'a';
    // ble_uerid[12] = 'v';
    // ble_uerid[13] = 'i';
    // ble_uerid[14] = 'v';
    // ble_uerid[15] = 'a';
    // ble_uerid[16] = 'v';
    // ble_uerid[17] = 'i';
    // ble_uerid[18] = 'v';
    // ble_uerid[19] = 'a';
    // ble_uerid[20] = 'v';
    // ble_uerid[21] = 'i';
    // ble_uerid[22] = 'v';
    // ble_uerid[23] = 'a';


    // ble_pwd[0] = 'C';
    // ble_pwd[1] = 'C';
    // ble_pwd[2] = 'N';
    // ble_pwd[3] = 'C';
    // ble_pwd[4] = 'v';
    // ble_pwd[5] = 'i';
    // ble_pwd[6] = 'v';
    // ble_pwd[7] = 'a';
    // ble_pwd[8] = 'v';
    // ble_pwd[9] = 'i';
    // ble_pwd[10] = 'v';
    // ble_pwd[11] = 'a';
    // ble_pwd[12] = 'v';
    // ble_pwd[13] = 'i';
    // ble_pwd[14] = 'v';
    // ble_pwd[15] = 'a';
    // ble_pwd[16] = 'v';
    // ble_pwd[17] = 'i';
    // ble_pwd[18] = 'v';
    // ble_pwd[19] = 'a';
    // ble_pwd[20] = 'v';
    // ble_pwd[21] = 'i';
    // ble_pwd[22] = 'v';
    // ble_pwd[23] = 'a';

    if(Ble_User.UseridUpdate)
    {
        ret = 1;
    }
    else
    {
        ret = 0;
    }

    return ret;
}

void Get_Ble_Raw_Data(uint8_t *data, uint32_t len)
{
    uint8_t err = 0;
    uint8_t crc = 0;

    if(len > 1024)
    {
        return;
    }
    

    if(data[0] == 0x24)
    {
        if(RecCtrl.Sts == BleRec_Idle)
        {
            // printf("receive data:");
            //     for(uint16_t i = 0; i< len; i++)
            //     {
            //         printf(" %x ", data[i]);
            //     }
            //     printf("\r\n");

            //     printf("\r\n");

            RecCtrl.RecLen = 0;
            memcpy(( uint8_t * )&BleRecData.Data[RecCtrl.RecLen], data, len);
            RecCtrl.TotalLen = BleRecData.Msg.Lenth +1 ;
            RecCtrl.RecLen += len;
            if(RecCtrl.RecLen >= RecCtrl.TotalLen)
            {
                crc = tp_Ble_Crc(BleRecData.Data, RecCtrl.TotalLen - 2);

                // printf("receive data:");
                // for(uint16_t i = 0; i< RecCtrl.TotalLen; i++)
                // {
                //     printf(" %x ", BleRecData.Data[i]);
                // }
                // printf("\r\n");

                // printf("rec crc = %d\r\n", crc);


                if((BleRecData.Data[RecCtrl.TotalLen - 1] != 0x0A) || (crc != BleRecData.Data[RecCtrl.TotalLen - 2]))
                {
                    Ble_Clear_Rx_Buffer();
                    RecCtrl.Sts = BleRec_Idle;
                }
                else
                {
                    RecCtrl.Sts = BleRec_Suc;

                    xSemaphoreGive(BleRecSuc_Semaphore);
                }
            }
            else
            {
                RecCtrl.Sts = BleRec_Start;

                // printf("BleRec_Start \r\n");
            }
        }
    }
    else
    {
        if(RecCtrl.Sts == BleRec_Start)
        {
            if((RecCtrl.RecLen+len) <= RecCtrl.TotalLen)
            {
                memcpy(( uint8_t * )&BleRecData.Data[RecCtrl.RecLen], data, len);
                RecCtrl.RecLen += len;

                if(RecCtrl.RecLen >= RecCtrl.TotalLen)
                {
                    crc = tp_Ble_Crc(BleRecData.Data, RecCtrl.TotalLen - 2);

                    // printf("receive data:");
                    // for(uint16_t i = 0; i< RecCtrl.TotalLen; i++)
                    // {
                    //     printf(" %x ", BleRecData.Data[i]);
                    // }
                    // printf("\r\n");

                    // printf("rec crc = %d\r\n", crc);

                    if((BleRecData.Data[RecCtrl.TotalLen - 1] != 0x0A) || (crc != BleRecData.Data[RecCtrl.TotalLen - 2]))
                    {
                        Ble_Clear_Rx_Buffer();
                        RecCtrl.Sts = BleRec_Idle;
                    }
                    else
                    {
                        RecCtrl.Sts = BleRec_Suc;

                        xSemaphoreGive(BleRecSuc_Semaphore);
                    }
                }
            }
            else
            {
                //len err
                Ble_Clear_Rx_Buffer();
                RecCtrl.Sts = BleRec_Idle;
            }
        }
    }

}



/**************************************************************************/

/**************************************************************************/

void Ble_Msg_Authr_RLY(void )
{
    uint8_t total_frame = 0;
    uint8_t trans_len = 0;
    int err;
    //Authr suc
    BleTransData.Msg.FrameHeader = 0x24;
    BleTransData.Msg.Cmd = 0x58;
    BleTransData.Msg.Lenth = 104;
    if((BleTransData.Msg.Lenth+1) % 20 == 0)
    {
        total_frame = (BleTransData.Msg.Lenth+1) / 20;
    }
    else
    {
        total_frame = (BleTransData.Msg.Lenth+1) / 20 + 1;
    }
    
    if(Ble_Get_User_Info())
    {
        memcpy(( uint8_t * )&BleTransData.Msg.Param[0], ble_key, 32);
        memcpy(( uint8_t * )&BleTransData.Msg.Param[32], ble_uerid, 32);
        memcpy(( uint8_t * )&BleTransData.Msg.Param[64], ble_pwd, 32);
        memcpy(( uint8_t * )&BleTransData.Msg.Param[96], flavor, 4);
    }
    BleTransData.Data[BleTransData.Msg.Lenth - 1] = tp_Ble_Crc(BleTransData.Data, BleTransData.Msg.Lenth - 1);
    BleTransData.Data[BleTransData.Msg.Lenth] = 0x0A;

    for(uint8_t i = 0; i < total_frame; i++)
    {
        if(((BleTransData.Msg.Lenth+1) - 20*i) >= 20)
        {
            trans_len = 20;
        }
        else
        {
            trans_len = (BleTransData.Msg.Lenth+1) - 20*i;
        }

        // printf("trans_len = %d\r\n", trans_len);

        // printf("trans data:");
        // for(uint16_t j = 0; j< trans_len; j++)
        // {
        //     printf(" %x ", BleTransData.Data[j + i*20]);
        // }
        // printf("\r\n");

        // printf("\r\n");

        err = bsp_Ble_Gatts_Send_Indicate( trans_len, &BleTransData.Data[i*20]);

        // vTaskDelay(1);
    }
}

void Ble_MsgRec_Authr_Result_Analysis(void )
{
    //Authr result
    if(BleRecData.Msg.Param[0] == 0)
    {
        Ble_User.Ble_Sts = Ble_Authr;
        Ble_User.Request_Navi = 1;

        ESP_LOGE("BLE USER","Authr suc\n");
    }
}



void Ble_Msg_RequestNavi_RLY(void )
{
    uint8_t total_frame = 0;
    uint8_t trans_len = 0;

    if(Ble_User.Request_Navi)
    {
        BleTransData.Msg.FrameHeader = 0x24;
        BleTransData.Msg.Cmd = 0x14;
        BleTransData.Msg.Lenth = 9;
        if((BleTransData.Msg.Lenth+1) % 20 == 0)
        {
            total_frame = (BleTransData.Msg.Lenth+1) / 20;
        }
        else
        {
            total_frame = (BleTransData.Msg.Lenth+1) / 20 + 1;
        }

        BleTransData.Msg.Param[0] = 1;
        BleTransData.Msg.Param[1] = 80;
        BleTransData.Msg.Param[2] = 0;
        BleTransData.Msg.Param[3] = 3;
        BleTransData.Msg.Param[4] = 0;
        
        BleTransData.Data[BleTransData.Msg.Lenth - 1] = tp_Ble_Crc(BleTransData.Data, BleTransData.Msg.Lenth - 1);
        BleTransData.Data[BleTransData.Msg.Lenth] = 0x0A;

        for(uint8_t i = 0; i < total_frame; i++)
        {
            if(((BleTransData.Msg.Lenth+1) - 20*i) >= 20)
            {
                trans_len = 20;
            }
            else
            {
                trans_len = (BleTransData.Msg.Lenth+1) - 20*i;
            }

            // printf("trans_len = %d\r\n", trans_len);

            // printf("trans data:");
            // for(uint16_t j = 0; j< trans_len; j++)
            // {
            //     printf(" %x ", BleTransData.Data[j + i*20]);
            // }
            // printf("\r\n");

            // printf("\r\n");

            bsp_Ble_Gatts_Send_Indicate( trans_len, &BleTransData.Data[i*20]);

            // vTaskDelay(1);
        }

        Ble_User.Request_Navi = 0;

    }


    
}





void Ble_Msg_RequestTime(void )
{
    uint8_t total_frame = 0;
    uint8_t trans_len = 0;

    if((Ble_User.Ble_Sts >= Ble_Authr) && (BleTime.TimeReqCnt > 0))
    {
        BleTransData.Msg.FrameHeader = 0x24;
        BleTransData.Msg.Cmd = 0x55;
        BleTransData.Msg.Lenth = 4;
        if((BleTransData.Msg.Lenth+1) % 20 == 0)
        {
            total_frame = (BleTransData.Msg.Lenth+1) / 20;
        }
        else
        {
            total_frame = (BleTransData.Msg.Lenth+1) / 20 + 1;
        }
        
        BleTransData.Data[BleTransData.Msg.Lenth - 1] = tp_Ble_Crc(BleTransData.Data, BleTransData.Msg.Lenth - 1);
        BleTransData.Data[BleTransData.Msg.Lenth] = 0x0A;

        for(uint8_t i = 0; i < total_frame; i++)
        {
            if(((BleTransData.Msg.Lenth+1) - 20*i) >= 20)
            {
                trans_len = 20;
            }
            else
            {
                trans_len = (BleTransData.Msg.Lenth+1) - 20*i;
            }

            bsp_Ble_Gatts_Send_Indicate( trans_len, &BleTransData.Data[i*20]);
        }
    }
}



void Ble_MsgRec_Navi_Analysis(void )
{
    uint32_t aaa = 0;
    //Navi data
    Ble_Navi_Data.Navi_Sts = BleRecData.Msg.Param[0];
    Ble_Navi_Data.Navi_Turn = BleRecData.Msg.Param[1];
    Ble_Navi_Data.Navi_Dte[0] = BleRecData.Msg.Param[2];
    Ble_Navi_Data.Navi_Dte[1] = BleRecData.Msg.Param[3];
    Ble_Navi_Data.Navi_Dte[2] = BleRecData.Msg.Param[4];
    Ble_Navi_Data.Navi_Dte[3] = BleRecData.Msg.Param[5];


    // printf("Navi sts %d    Navi_Turn %x   Navi_Dte0 %x   Navi_Dte1 %x   Navi_Dte2 %x   Navi_Dte3 %x\r\n", 
    // Ble_Navi_Data.Navi_Sts, Ble_Navi_Data.Navi_Turn, Ble_Navi_Data.Navi_Dte[0], Ble_Navi_Data.Navi_Dte[1], Ble_Navi_Data.Navi_Dte[2],Ble_Navi_Data.Navi_Dte[3]);

    aaa = Ble_Navi_Data.Navi_Dte[3];
    aaa <<= 8;
    aaa |= Ble_Navi_Data.Navi_Dte[2];
    aaa <<= 8;
    aaa |= Ble_Navi_Data.Navi_Dte[1];
    aaa <<= 8;
    aaa |= Ble_Navi_Data.Navi_Dte[0];


    // printf("navi sts = %x; navi turn = %d; navi dest = %ld\n", Ble_Navi_Data.Navi_Sts, Ble_Navi_Data.Navi_Turn, aaa);


    // printf("Navi sts %d    Navi_Turn %x   Navi_Dte0 %x   Navi_Dte1 %x   Navi_Dte2 %x   Navi_Dte3 %x\r\n", 
    // Ble_Navi_Data.Navi_Sts, Ble_Navi_Data.Navi_Turn, Ble_Navi_Data.Navi_Dte[0], Ble_Navi_Data.Navi_Dte[1], Ble_Navi_Data.Navi_Dte[2],Ble_Navi_Data.Navi_Dte[3]);


    Ble_User.Navi_Updat = 1;
    Ble_User.Navi_T = 0;
}


//11 12 hour
//14 15 min
//17 18 sec
void Ble_MsgRec_Time_Analysis(void )
{
    uint8_t wtemp[6] = {0};

    Char_To_Dec(BleRecData.Msg.Param[11], &wtemp[0]);
    Char_To_Dec(BleRecData.Msg.Param[12], &wtemp[1]);

    BleTime.u8Hour = wtemp[0] * 10 + wtemp[1];

    Char_To_Dec(BleRecData.Msg.Param[14], &wtemp[2]);
    Char_To_Dec(BleRecData.Msg.Param[15], &wtemp[3]);

    BleTime.u8Minute = wtemp[2] * 10 + wtemp[3];

    Char_To_Dec(BleRecData.Msg.Param[17], &wtemp[4]);
    Char_To_Dec(BleRecData.Msg.Param[18], &wtemp[5]);

    BleTime.u8Sec = wtemp[4] * 10 + wtemp[5];

    if(BleTime.u8Sec < 59)
    {
        BleTime.u8Sec += 1;
    }
    else
    {
        BleTime.u8Sec = 0;
        if(BleTime.u8Minute < 59)
        {
            BleTime.u8Minute += 1;
        }
        else
        {
            BleTime.u8Minute = 0;
            if(BleTime.u8Hour < 23)
            {
                BleTime.u8Hour ++;
            }
            else
            {
                BleTime.u8Hour = 0;
            }
        }
    }


    if(BleTime.u8Hour < 24 && BleTime.u8Minute < 60 && BleTime.u8Sec < 60)
    {
        if(BleTime.TimeReqCnt > 0)
        {
            BleTime.TimeReqCnt --;
            BleTime.TimeUpdate = 1;

            // Uart_Send_Id12_Pro();
        }
    }
}


app_Ble_Time_Info_Struct *Get_Ble_TimeInfo(void )
{
    app_Ble_Time_Info_Struct *ret = NULL;
    if(BleTime.TimeUpdate)
    {
        BleTime.TimeUpdate = 0;
        ret = (app_Ble_Time_Info_Struct *)&BleTime;
    }
    return ret;
}



void Ble_MsgRec_Navi_Timeout(void )
{
    if(Ble_User.Navi_Updat)
    {
        Ble_User.Navi_T++;
        if(Ble_User.Navi_T >= 100)
        {
            Ble_User.Navi_Updat = 0;
            Ble_User.Navi_T = 0;
        }
    }
    else
    {
        Ble_User.Navi_T = 0;
    }



}




void Ble_Connect_Event_Pro(void )
{
    Ble_User.Ble_Sts = Ble_Conn;
    Ble_User.Request_Navi = 0;
    Ble_User.Navi_Updat = 0;
    Ble_User.Navi_T = 0;

    Ble_Clear_Tx_Buffer();
    Ble_Clear_Rx_Buffer();

    BleTime.TimeReqCnt = 5;

}


void Ble_DisConnect_Event_Pro(void )
{
    Ble_User.Ble_Sts = Ble_Idle;
    Ble_User.Request_Navi = 0;
    Ble_User.Navi_Updat = 0;
    Ble_User.Navi_T = 0;

    RecCtrl.RecLen = 0;
    RecCtrl.TotalLen = 0;
    RecCtrl.Sts = BleRec_Idle;

    Ble_Navi_Data.Navi_Sts = 0;
    Ble_Navi_Data.Navi_Turn = 0;
    for(uint8_t i=0; i<sizeof(Ble_Navi_Data.Navi_Dte); i++)
    {
        Ble_Navi_Data.Navi_Dte[i] = 0;
    }
    

    Ble_Clear_Tx_Buffer();
    Ble_Clear_Rx_Buffer();

    BleTime.TimeReqCnt = 0;
}


void Ble_User_Task(void *pvParameter)
{

    while (1)
    {
        if (pdTRUE == xSemaphoreTake(BleRecSuc_Semaphore, portMAX_DELAY)) 
        {
            if(RecCtrl.Sts == BleRec_Suc)
            {
                if(BleRecData.Msg.Cmd == EC_BTP_P2C_CLIENT_INFO)
                {
                    Ble_Msg_Authr_RLY();
                }
                else if(BleRecData.Msg.Cmd == EC_BTP_P2C_CHECK_AUTH_RESULT)
                {
                    Ble_MsgRec_Authr_Result_Analysis();
                    Ble_Msg_RequestNavi_RLY();
                }
                else if(BleRecData.Msg.Cmd == EC_BTP_P2C_HUD)
                {
                    Ble_MsgRec_Navi_Analysis();
                }
                else if(EC_BTP_TIME_SYN == BleRecData.Msg.Cmd)
                {
                    Ble_MsgRec_Time_Analysis();
                }

                Ble_Clear_Tx_Buffer();
                Ble_Clear_Rx_Buffer();
                RecCtrl.Sts = BleRec_Idle;
            }
        }
    }
    vTaskDelete(NULL);
}

void Ble_User_Task_Cyc(void *pvParameter)
{
    while (1)
    {
        Ble_Msg_RequestTime();
        vTaskDelay(1000);
    }
    vTaskDelete(NULL);
}


void Ble_User_Init(void )
{
    BleRecSuc_Semaphore =     xSemaphoreCreateBinary();

    Ble_User.Ble_Sts = Ble_Idle;
    Ble_User.Request_Navi = 0;
    Ble_User.Navi_Updat = 0;
    Ble_User.Navi_T = 0;
    Ble_User.UseridUpdate = 0;

    RecCtrl.RecLen = 0;
    RecCtrl.TotalLen = 0;
    RecCtrl.Sts = BleRec_Idle;

    Ble_Navi_Data.Navi_Sts = 0;
    Ble_Navi_Data.Navi_Turn = 0;
    for(uint8_t i=0; i<sizeof(Ble_Navi_Data.Navi_Dte); i++)
    {
        Ble_Navi_Data.Navi_Dte[i] = 0;
    }
    

    Ble_Clear_Tx_Buffer();
    Ble_Clear_Rx_Buffer();


    xTaskCreatePinnedToCore(Ble_User_Task, "Ble_User", 4096, NULL, 10, NULL, 0);
    xTaskCreatePinnedToCore(Ble_User_Task_Cyc, "Ble_User_Cyc", 4096, NULL, 9, NULL, 0);

}

