#include "Cyton_Esp12Data.h"
#include "usart.h"	
#include <string.h>
#include "delay.h"       
#include "led.h"       
#include "key.h"
#include "Timer.h"
#include "ADS129x.h"
#include "ESP8266.h"
#include "cJSON.h"

#include "myQueue.h"


typedef struct stCytron_DevSeting {
    uint8_t aucRate;
    uint8_t aucStreamStat;
} CYTON_DEVSETING_T;

static int g_iOpenguiPort = -1;
static uint8_t g_szOpenguiIP[16] = {0};
static int g_iOpenguiFd = 4;
static uint8_t g_iOepnguiConnnectStat = 0;
static CYTON_DEVSETING_T g_stCytron_DevSeting;

static int Ctron_atoi(uint8_t *szData, int iLen)
{
    //0,11:123456711
    uint8_t szTmp[4] = {0};

    if (iLen > 4) {
        return -1;
    }

    strncpy(szTmp, szData, iLen);
    return atoi(szTmp);
}


static int Ctron_GetDataLen(uint8_t *szData, int iLen)
{
    /* 9:1234567 */
    uint8_t iColon = 0;
    uint8_t szTmp[4] = {0};

    while (iColon < 5) {
        if(*(szData + iColon) == ':') {
            iColon ++;
            break;
        }

        iColon ++;
    }

    if (iColon <= 4) {
        strncpy(szTmp, szData, iColon);
    } else {
        return -1;
    }

    return atoi(szTmp);
}

static int ctron_GetRate(uint8_t *szData, int iLen)
{
    uint8_t *pszIndex = NULL;

    pszIndex = strstr(szData, "~");
    if (NULL != pszIndex) {
        return Ctron_atoi(pszIndex + 1, 1);
    }

    return -1;    
}

static int ctron_Esp12Data_PraseTcpJson(int iFD, uint8_t *szData, int iLen)
{
    //{"connected":true,"delimiter":true,"ip":"192.168.4.2","output":"raw","port":6677,"latency":10000}
    cJSON *cjson_data;
    cJSON *cjson_str;

    uint8_t *pszIndex = 0;
    
    pszIndex = strstr(szData, "{");
    if (NULL == pszIndex) {
        ESP8266_DEBUG("\r\ntcp json prase failed1111111111: %s\n", szData);
        return -1;
    }

    cjson_data = cJSON_Parse(pszIndex);
    if (cjson_data) {
	    cjson_str = cJSON_GetObjectItem(cjson_data,"ip");
	    if (cjson_str) {
            sprintf(g_szOpenguiIP, "%s", cjson_str->valuestring);
            ESP8266_DEBUG("TCP Json g_szOpenguiIP %s\n", g_szOpenguiIP);
        }

        cjson_str = cJSON_GetObjectItem(cjson_data,"port");
	    if (cjson_str) {
            g_iOpenguiPort = cjson_str->valueint;
            ESP8266_DEBUG("TCP Json g_szOpengui port %d\n", g_iOpenguiPort);
        }

        cjson_str = cJSON_GetObjectItem(cjson_data,"command");
	    if (cjson_str) {
            g_stCytron_DevSeting.aucRate = ctron_GetRate(cjson_str->valuestring, strlen(cjson_str->valuestring));
            ESP8266_DEBUG("g_stCytron_DevSeting.aucRate %d\n", g_stCytron_DevSeting.aucRate);
        }

	    cJSON_Delete(cjson_data);

        return 0;
    }

    ESP8266_DEBUG("\r\ntcp json prase failed: %s\n", szData);

    return -1;
}

//;
//const char *szBoardRspJson = 
const char *szBoardRsp = "HTTP/1.0 200 Ok\r\n"
    "Content-Type: text/json\r\n"
    "Access-Control-Allow-Origin: *\r\n"
    "Content-Length: 96\r\n"
    "Connection: close\r\n"
    "\r\n"
    "{\"board_connected\":true,\"board_type\":\"cyton\",\"num_channels\":8,\"gains\":[24,24,24,24,24,24,24,24]}";

const char *szTcpRsp = "HTTP/1.0 200 Ok\r\n"
    "Content-Type: text/json\r\n"
    "Access-Control-Allow-Origin: *\r\n"
    "Content-Length: 97\r\n"
    "Connection: close\r\n"
    "\r\n"
    "{\"connected\":true,\"delimiter\":true,\"ip\":\"192.168.4.2\",\"output\":\"raw\",\"port\":6677,\"latency\":10000}";

const char *szCommandHz = "HTTP/1.0 200 Ok\r\n"
    "Content-Type: text/json\r\n"
    "Access-Control-Allow-Origin: *\r\n"
    "Content-Length: 32\r\n"
    "Connection: close\r\n"
    "\r\n"
    "Success: Sample rate is 1000Hz";

const char *szStreamStartRsp = "HTTP/1.0 200 Ok\r\n"
    "Content-Type: text/json\r\n"
    "Access-Control-Allow-Origin: *\r\n"
    "Content-Length: 16\r\n"
    "Connection: close\r\n"
    "\r\n"
    "Stream started\r\n";

const char *szStreamStopRsp = "HTTP/1.0 200 Ok\r\n"
    "Content-Type: text/json\r\n"
    "Access-Control-Allow-Origin: *\r\n"
    "Content-Length: 16\r\n"
    "Connection: close\r\n"
    "\r\n"
    "Stream stopped\r\n";

//{"connected":true,"delimiter":true,"ip":"192.168.4.2","output":"raw","port":6677,"latency":10000}
void Ctron_Esp12Data_Recv(int iFD, uint8_t *szData, int iLen)
{
    int iRet = -1;
    /* GET /board HTTP/1.0
    Host: 192.168.4.1:80 
    rsp:
    HTTP/1.0 200 Ok\r\n
    Content-Type: text/json\r\n
    Access-Control-Allow-Origin: *\r\n
    Content-Length: 96\r\n
    Connection: close\r\n
    \r\n
    {"board_connected":true,"board_type":"cyton","num_channels":8,"gains":[24,24,24,24,24,24,24,24]}
    */

    if (strstr(szData, "GET /board")) {
        ESP8266_DEBUG("Board rsp length %d\n", strlen(szBoardRsp));
        Ctron_Esp12Data_Send(iFD, (uint8_t *)szBoardRsp, strlen(szBoardRsp), 1);

    } else if (strstr(szData, "\"port\":6677")) {
        iRet = ctron_Esp12Data_PraseTcpJson(iFD, (uint8_t *)szData, iLen);
        if (iRet == 0) {
            ESP8266_DEBUG("tcp start connect %s:%d\n", g_szOpenguiIP, g_iOpenguiPort);
            ESP8266_SendCmd("AT+CIPSTART=4,\"TCP\",\"192.168.4.2\",6677\r\n", "OK", 1000);
            ESP8266_DEBUG("tcp start rsp\n");
            Ctron_Esp12Data_Send(iFD, (uint8_t *)szTcpRsp, strlen(szTcpRsp), 1);
        }

	} else if (strstr(szData, "\"command\"")) {
        iRet = ctron_Esp12Data_PraseTcpJson(iFD, (uint8_t *)szData, iLen);
        if (iRet == 0) {
            ESP8266_DEBUG("command start rsp\n");
            Ctron_Esp12Data_Send(iFD, (uint8_t *)szCommandHz, strlen(szCommandHz), 1);
        } else {

        }

    } else if (strstr(szData, "/stream/start")) {
        ESP8266_DEBUG("stream start rsp\n");
        g_stCytron_DevSeting.aucStreamStat = 1;
        Ctron_Esp12Data_Send(iFD, (uint8_t *)szStreamStartRsp, strlen(szStreamStartRsp), 1);
        CytonProcess_TimerCollStart(1000);
    } else if (strstr(szData, "/stream/stop")) {
        ESP8266_DEBUG("stream stop rsp\n");
        g_stCytron_DevSeting.aucStreamStat = 0;
        CytonProcess_TimerCollStop();
        Ctron_Esp12Data_Send(iFD, (uint8_t *)szStreamStopRsp, strlen(szStreamStopRsp), 1);
    } else {
        ESP8266_DEBUG("Prase failed\n");
    }
}

void Ctron_Esp12Data_Send(int iFD, uint8_t *szData, int iLen, int iClose)
{
    uint8_t szCmd[64] = 0;

    sprintf(szCmd, "AT+CIPSEND=%d,%d\r\n", iFD, iLen);
    /* AT+CIPSEND=<link ID>,<length> */
    ESP8266_SendCmd(szCmd, ">", 100);
    ESP8266_SendData(szData, iLen);

    //delay_ms(20);

    if (iClose) {
        delay_ms(200);
        memset(szCmd, 0, sizeof(szCmd));
        sprintf(szCmd, "AT+CIPCLOSE=%d\r\n", iFD);
        ESP8266_SendCmd(szCmd, "OK", 50);
    }
}


/* +IPD,0,9:1234567 */
void Ctron_Esp12Data_Loop()
{
    uint8_t *pszIndex = NULL;
    uint8_t *pszData = NULL;
    int iFd = -1;
    int iLen = -1;

    pszIndex = strstr(USART2_RX_BUF, "+IPD,");
    if (NULL != pszIndex) {
        iFd = Ctron_atoi(pszIndex + 5, 1);
        iLen = Ctron_GetDataLen(pszIndex + 7, USART2_RX_LEN - 7);
        ESP8266_DEBUG("Ctron_Esp12Data_Loop fd [%d](lengh=%d): %s\r\n", iFd, iLen, ESP8266_RX_BUF);

        pszIndex = strstr(USART2_RX_BUF, ":");
        if (iFd >= 0) {
            Ctron_Esp12Data_Recv(iFd, pszIndex + 1, iLen);
        }
        ESP8266_CLEAR();
    }
}

int CytonEsp12_DataGetReportFd()
{
    return g_iOpenguiFd;
}

int CytonEsp12_StreamStat()
{
    return g_stCytron_DevSeting.aucStreamStat;
}

int CytonEsp12_GetCurrentRate()
{
    int iRate = g_stCytron_DevSeting.aucRate;
    int iRet = 1000;

    switch(iRate) {
        case 0:
            iRet = 16000;
            break;
        case 1:
            iRet = 8000;
            break;
        case 2:
            iRet = 4000;
            break;
        case 3:
            iRet = 2000;
            break;
        case 4:
            iRet = 1000;
            break;
        case 5:
            iRet = 500;
        case 6:
            iRet = 250;
            break;
        default:
            break;
    }

    return iRet;
}


