#include "gps.h"


//#define TEST 					1  //测试使用,去除的时候可以接触代码的调用
#define parse					1 // 测试使用



/**
提示: 虽然 BLE 以及 GPS都是DMA+ UART接收，但是它们都有所不同
BLE --- DMA + IDLE 中断  循环 DMA + 空闲中断触发处理  UART IDLE  
GPS --- DMA +固定长度 + TC中断   设置固定长度 DMA    DMA传输完成中断

**/


//外部引入
extern UART_HandleTypeDef huart2;
extern DMA_HandleTypeDef handle_GPDMA1_Channel3;


//全局数据变量定义
uint8_t GPS_DMA_RX_BUF[GPS_DMA_RX_BUF_LEN];  //用于DMA接收缓冲
_GPSData GPS;

void GPS_Init(void)
{
    HAL_UARTEx_ReceiveToIdle_IT(&huart2, GPS_DMA_RX_BUF, GPS_DMA_RX_BUF_LEN);
//		HAL_UARTEx_ReceiveToIdle_DMA(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN);
}

#ifdef parse
// GPS数据解析
//void parseGpsBuffer()
//{
//	char *subString;
//	char *subStringNext;
//	char i = 0;
//	
//	if(GPS.isGetData)
//	{
//		GPS.isGetData = 0; // 把标志位置为1
//		
//		char usefullBuffer[2] = {0};
//		for(i = 0; i <= 6; i++)
//		{
//			if(i == 0)
//			{
//				
//				subString = strstr(GPS.GPS_Buffer,",");
//				if(!subString)return;
//			}
//			else
//			{
//				subString++;
//				subStringNext = strstr(subString,",");
//				if(!subStringNext)return;
//				
//				switch(i)
//				{
//					case 1:
//						memcpy(GPS.UTCTime,subString,subStringNext - subString);
//						break;
//					case 2:
//						memcpy(usefullBuffer,subString,subStringNext - subString);
//						break;
//					case 3:
//						memcpy(GPS.latitude,subString,subStringNext - subString);
//						break;
//					case 4:
//						memcpy(GPS.N_S,subString,subStringNext - subString);
//						break;
//					case 5:
//						memcpy(GPS.longitude,subString,subStringNext - subString);
//						break;
//					case 6:
//						memcpy(GPS.E_W,subString,subStringNext - subString);
//						break;
//					default:break;
//				}
//				
//				subString = subStringNext;
//			}
//			
//		}
//		GPS.isParseData = 1;
//		GPS.isUsefull = (usefullBuffer[0] == 'A') ? 1 : 0;
//	}
//	
//}


//void parseGpsBuffer(void)
//{
//    if (!GPS.isGetData) return;
//    GPS.isGetData = 0;

//    /* ----------- 句型判别 ------------ */
//    const char *p = GPS.GPS_Buffer;

//    /* ★ RMC ----------------------------------------------------- */
//    if (!strncmp(p, "$GNRMC", 6) || !strncmp(p, "$GPRMC", 6))
//    {
//        char status, lat[16], ns[3], lon[16], ew[3];
//        if (sscanf(p,
//                   "$%*[^,],%*[^,],%c,%15[^,],%2[^,],%15[^,],%2[^,],",
//                   &status, lat, ns, lon, ew) == 5)
//        {
//            if (status == 'A')                      /* 定位有效 */
//            {
//                strcpy(GPS.latitude,  lat);
//                strcpy(GPS.N_S,       ns);
//                strcpy(GPS.longitude, lon);
//                strcpy(GPS.E_W,       ew);
//                GPS.isParseData = 1;
//                GPS.isUsefull   = 1;
//            }
//        }
//        return;
//    }

//    /* ★ GGA ----------------------------------------------------- */
//    if (!strncmp(p, "$GNGGA", 6) || !strncmp(p, "$GPGGA", 6))
//    {
//        int q;  char lat[16], ns[3], lon[16], ew[3];
//        if (sscanf(p,
//                   "$%*[^,],%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%d,",
//                   lat, ns, lon, ew, &q) == 5)
//        {
//            if (q > 0)                              /* q=0 无定位 */
//            {
//                strcpy(GPS.latitude,  lat);
//                strcpy(GPS.N_S,       ns);
//                strcpy(GPS.longitude, lon);
//                strcpy(GPS.E_W,       ew);
//                GPS.isParseData = 1;
//                GPS.isUsefull   = 1;
//            }
//        }
//        return;
//    }

//    /* ★ GLL ----------------------------------------------------- */
//    if (!strncmp(p, "$GNGLL", 6) || !strncmp(p, "$GPGLL", 6))
//    {
//        char status, lat[16], ns[3], lon[16], ew[3];
//        if (sscanf(p,
//                   "$%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%*[^,],%c",
//                   lat, ns, lon, ew, &status) == 5)
//        {
//            if (status == 'A')
//            {
//                strcpy(GPS.latitude,  lat);
//                strcpy(GPS.N_S,       ns);
//                strcpy(GPS.longitude, lon);
//                strcpy(GPS.E_W,       ew);
//                GPS.isParseData = 1;
//                GPS.isUsefull   = 1;
//            }
//        }
//    }
//}

/* === ① 行缓存区 & 推送函数 === */
static char line_buf[GPS_Buffer_Length];
static uint16_t line_w = 0;

void GPS_LinePush(uint8_t ch)
{
    if (ch == '\n') {                     /* 正常行结束 */
        line_buf[line_w] = '\0';


        /* A. 如果不是 '$' 开头，说明它只是上一句的后半截 → 直接拼接 */
        if (line_buf[0] != '$' && GPS.isGetData == 0 && GPS.GPS_Buffer[0] == '$')
        {
            strncat(GPS.GPS_Buffer, line_buf, GPS_Buffer_Length - strlen(GPS.GPS_Buffer) - 1);
        }
        else        /* B. 正常完整新句 */
        {
            strncpy(GPS.GPS_Buffer, line_buf, GPS_Buffer_Length);
        }

        line_w = 0;
        GPS.isGetData = 1;
        tx_event_flags_set(&system_events, EVENT_GPS_DATA_READY, TX_OR);
        return;
    }
}

/* === ② 新解析器：只要经纬度 === */
void parseGpsBuffer(void)
{
    if (!GPS.isGetData) return;
    GPS.isGetData = 0;
    GPS.isParseData = 0;
    GPS.isUsefull  = 0;

    const char *p = GPS.GPS_Buffer;
    /* ---- $GxRMC ---- */
    if (!strncmp(p, "$GNRMC", 6) || !strncmp(p, "$GPRMC", 6)) {
        char s, lat[16], ns[3], lon[16], ew[3];
        if (sscanf(p,
                   "$%*[^,],%*[^,],%c,%15[^,],%2[^,],%15[^,],%2[^,],",
                   &s, lat, ns, lon, ew) == 5 && s == 'A') {
            strcpy(GPS.latitude, lat); strcpy(GPS.N_S, ns);
            strcpy(GPS.longitude, lon); strcpy(GPS.E_W, ew);
            GPS.isParseData = GPS.isUsefull = 1;
        }
        return;
    }
    /* ---- $GxGGA ---- */
    if (!strncmp(p, "$GNGGA", 6) || !strncmp(p, "$GPGGA", 6)) {
        int q; char lat[16], ns[3], lon[16], ew[3];
        if (sscanf(p,
            "$%*[^,],%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%d,",
            lat, ns, lon, ew, &q) == 5 && q > 0) {
            strcpy(GPS.latitude, lat); strcpy(GPS.N_S, ns);
            strcpy(GPS.longitude, lon); strcpy(GPS.E_W, ew);
            GPS.isParseData = GPS.isUsefull = 1;
        }
        return;
    }
    /* ---- $GxGLL ---- */
    if (!strncmp(p, "$GNGLL", 6) || !strncmp(p, "$GPGLL", 6)) {
        char s, lat[16], ns[3], lon[16], ew[3];
        if (sscanf(p,
            "$%*[^,],%15[^,],%2[^,],%15[^,],%2[^,],%*[^,],%c",
            lat, ns, lon, ew, &s) == 5 && s == 'A') {
            strcpy(GPS.latitude, lat); strcpy(GPS.N_S, ns);
            strcpy(GPS.longitude, lon); strcpy(GPS.E_W, ew);
            GPS.isParseData = GPS.isUsefull = 1;
        }
    }
}


#else // 这里是对于改进后的parse 解析 两个都需要进行测试
void parseGpsBuffer()
{
    char *fields[7];
    char *token;
    int fieldIndex = 0;

    if (GPS.isGetData)
    {
        GPS.isGetData = 0; // 把标志位置为0

        token = strtok(GPS.GPS_Buffer, ",");
        while (token != NULL && fieldIndex < 7)
        {
            fields[fieldIndex++] = token;
            token = strtok(NULL, ",");
        }

        if (fieldIndex == 7)
        {
            memcpy(GPS.UTCTime, fields[1], sizeof(GPS.UTCTime) - 1);
            GPS.UTCTime[sizeof(GPS.UTCTime) - 1] = '\0';

            memcpy(GPS.latitude, fields[3], sizeof(GPS.latitude) - 1);
            GPS.latitude[sizeof(GPS.latitude) - 1] = '\0';

            memcpy(GPS.N_S, fields[4], sizeof(GPS.N_S) - 1);
            GPS.N_S[sizeof(GPS.N_S) - 1] = '\0';

            memcpy(GPS.longitude, fields[5], sizeof(GPS.longitude) - 1);
            GPS.longitude[sizeof(GPS.longitude) - 1] = '\0';

            memcpy(GPS.E_W, fields[6], sizeof(GPS.E_W) - 1);
            GPS.E_W[sizeof(GPS.E_W) - 1] = '\0';

            GPS.isParseData = 1;
            GPS.isUsefull = (fields[2][0] == 'A') ? 1 : 0;
        }
    }
}


/*
改进点总结
使用 strtok 进行分隔：
更加简洁地分割字符串。
数组存储字段：
使用数组存储每个字段的指针，减少重复代码。
边界检查：
确保字段数量足够，避免数组越界。
字符串截断：
确保复制的字符串以 null 结尾，避免潜在的字符串处理问题。
*/
#endif

// 转换角度
double Convert_to_degrees(char *data)
{
	double temp = atof(data);
	int deg = (int)(temp / 100);
	double min = temp - deg * 100;
	return deg + (min / 60.0);
}


// 串口数据清除
void GPS_Data_CLR(void)
{
	memset(GPS_DMA_RX_BUF,0,GPS_DMA_RX_BUF_LEN);
	
}


//void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
//{
//	if(huart->Instance == USART2)
//	{
//		// 根据 Size 拷贝接收到的数据
//		memcpy(GPS.GPS_Buffer,GPS_DMA_RX_BUF,Size);
//		GPS.GPS_Buffer[Size] = '\0';
//		GPS.isGetData = 1;  //数据接收标志位置为1
//		
//		tx_event_flags_set(&system_events, EVENT_GPS_DATA_READY, TX_OR);
//		//重新开启接收
//		HAL_UARTEx_ReceiveToIdle_IT(&huart2,GPS_DMA_RX_BUF,GPS_DMA_RX_BUF_LEN);
//	}
//	
//}


// 如果需要使用到ThreadX 就把gps.h中的 TEST 宏定义加入
#ifdef  TEST


void gps_thread_entry(ULONG thread_input)
{
    GPS_Init();
    static int gps_first_fix_sent = 0;
	BleMessage msg;
    while (1)
    {
        ULONG events;
        tx_event_flags_get(&system_events, EVENT_GPS_DATA_READY, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);

        parseGpsBuffer();
//		HCBle_SendData("[GPS] isGetData=%d, isParseData=%d, isUsefull=%d, Buffer=%s\r\n",
//		GPS.isGetData, GPS.isParseData, GPS.isUsefull, GPS.GPS_Buffer);
        if (GPS.isParseData && GPS.isUsefull)
        {
            current_location.lat = Convert_to_degrees(GPS.latitude);
            current_location.lon = Convert_to_degrees(GPS.longitude);
            tx_event_flags_set(&system_events, EVENT_LOCATION_UPDATED, TX_OR);

			
//			msg.lat = current_location.lat;
//			msg.lon = current_location.lon;
//            snprintf(msg, sizeof(msg), "#{\"lat\":%.6f,\"lon\":%.6f,\"angle\":%.2f}\n",
//                     current_location.lat,
//                     current_location.lon,
//                     current_location.angle);
			BleMessage msg = current_location;
			tx_queue_send(&ble_tx_queue, &msg, TX_WAIT_FOREVER);

        }
    }
}


#endif


