#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "tb05_control.h"
#include "radio.h"
#include "project_config.h"
#include "stm32f10x_it.h"
#include "delay.h"
#include "string.h"
#include "HAL_uart.h"
#include "UART_FIFO.h"
#include "chip_id.h"
#include "sx126x_cmd_process.h"

struct STRUCT_USART_Fram TB05_Fram_Record_Struct = {0};
#define RESPONE_MAX_LENGTH 2048
#define TB05_LED_PIN GPIO_Pin_15
#define TB05_RST_PIN GPIO_Pin_1
#define TB05_RST_PORT GPIOA
#define TB05_RECV_CYCLE 80
#define TB05_MAX_RECV_TIMEOUT 5000

typedef enum
{
	BT_IDLE = 0,
	BT_READY,
	BT_ADV_TIME,
	BT_RENAME,
	BT_REBOOT,
	BT_DISCONN,
	BT_ADV,
	BT_CONNECTING, // 6
	BT_TRANSPARENT,
} tb05_status_t;
tb05_status_t tb05_status = BT_IDLE;

typedef enum
{
	NONE_RESPONE = 0,
	READY_RESPONE,
	BUSY_RESPONE,
	OK_RESPONE,
	ERROR_RESPONE,
	CONN_RESPONE,
	DISCONN_RESPONE,
	TRANSPARENT_DATA,
} respone_type_t;

typedef struct
{
	uint8_t respone_flag;
	uint16_t respone_wait_time;
	char repone_data[RESPONE_MAX_LENGTH];
} tb05_respone_data_t;
tb05_respone_data_t tb05_respone_data;

void TB05_USART(char *Data, int data_len)
{
	while (*Data != 0)
	{
		if (*Data == 0x5c)
		{ //'\'
			switch (*++Data)
			{
			case 'r':
				USART_SendData(USART2, 0x0d);
				Data++;
				break;
			case 'n':
				USART_SendData(USART2, 0x0a);
				Data++;
				break;
			default:
				Data++;
				break;
			}
		}else
			USART_SendData(USART2, *Data++);
		while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
			;
	}
}

/*ctrl pin and status pin init*/
void tb05_reset_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStructure.GPIO_Pin = TB05_RST_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(TB05_RST_PORT, &GPIO_InitStructure);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_InitStructure.GPIO_Pin = TB05_LED_PIN;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*reset tb05*/
void tb05_reset(void)
{
	GPIO_ResetBits(TB05_RST_PORT, TB05_RST_PIN);
	delay_ms(100);
	GPIO_SetBits(TB05_RST_PORT, TB05_RST_PIN);
	delay_ms(3000);
}

void tb05_init(void)
{
	tb05_reset_init();
	tb05_reset();
}

/*
	tb05 communication data processing
	detect ready msg --> check AT command --> set ADV name --> set slave mode and then adv 
	--> when connected run in TRANSPARENT mode to listen lora configuration data, parse and complete function configuration
*/

respone_type_t respone_data_process(void)
{
	respone_type_t respone_type = NONE_RESPONE;
	if (TB05_Fram_Record_Struct.InfBit.FramFinishFlag == 1)
	{
		TB05_Fram_Record_Struct.Data_RX_BUF[TB05_Fram_Record_Struct.InfBit.FramLength] = '\0';
		// printf("respone_data_process: %s\r\n", TB05_Fram_Record_Struct.Data_RX_BUF);
		if (strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "\r\nready\r\n") != NULL)
		{
			respone_type = READY_RESPONE;
		}
		else if (strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "ERROR")  || strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "Unknown cmd") != NULL)
		{
			respone_type = ERROR_RESPONE;
		}
		else if (strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "[Busy]") != NULL)
		{
			respone_type = BUSY_RESPONE;
		}
		else if (strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "+EVENT:BLE_CONNECTED") != NULL)
		{
			tb05_status = BT_TRANSPARENT;
			respone_type = CONN_RESPONE;
		}
		else if (strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "+EVENT:BLE_DISCONNECT") != NULL)
		{
			respone_type = DISCONN_RESPONE;
		}
		else if(strstr((char *)TB05_Fram_Record_Struct.Data_RX_BUF, "OK") != NULL )
		{
			respone_type = OK_RESPONE;
		}
		else
		{
			if (BT_TRANSPARENT == tb05_status && TB05_Fram_Record_Struct.InfBit.FramLength > 5)
			{
				sx126x_cmd_process(); // parse lora config msg
			}
			respone_type = NONE_RESPONE;
		}
		TB05_Fram_Record_Struct.InfBit.FramFinishFlag = 0;
		TB05_Fram_Record_Struct.InfBit.FramLength = 0;
		memset(TB05_Fram_Record_Struct.Data_RX_BUF, 0, 2048);
	}else{
		respone_type = NONE_RESPONE;
	}

	return respone_type;
}

// void bt_data_process(void) 
void tb05_data_proccess(void)
{
	static int delay_count = 0;
	static int wait_count = 0;
	int i = 0;
	char *ble_cmd;
	CHIP_ID_TypeDef chip_id;
	respone_type_t respone_type = NONE_RESPONE;
	ble_cmd = (char*)malloc(sizeof(char) * 30);
	for(i = 0; i < 30; i ++){
		ble_cmd[0] = 0;
	}
	if (delay_count % TB05_RECV_CYCLE == 0)
	{
		respone_type = respone_data_process();
	}
	delay_count++;
	switch (tb05_status)
	{
	case BT_IDLE:
		/*
		READY_RESPONE,
		BUSY_RESPONE,
		OK_RESPONE,
		ERROR_RESPONE,
		CONN_RESPONE,
		DISCONN_RESPONE,
		*/
		if (READY_RESPONE == respone_type)
		{
			tb05_status = BT_READY;
			wait_count = 0;
			printf("BT_READY\r\n");
		}else{
			wait_count++;
			if (wait_count > TB05_MAX_RECV_TIMEOUT)
			{
				tb05_status = BT_REBOOT;
				wait_count = 0;
			}
		}
		break;
	case BT_REBOOT:
		tb05_status = BT_IDLE;
		printf("reset tb05");
		tb05_reset();
		break;
	case BT_READY:
		wait_count++;
		if (wait_count > 1)
		{
			switch (respone_type)
			{
			case READY_RESPONE:
				printf("BT_READY\r\n");
			case ERROR_RESPONE:
			case BUSY_RESPONE:
				wait_count = 0;
				break;
			case OK_RESPONE:
				tb05_status = BT_ADV_TIME;
				wait_count = 0;
				printf("BT_ADV_TIME\r\n");
				break;
			case NONE_RESPONE:
				if (wait_count > TB05_MAX_RECV_TIMEOUT)
				{
					tb05_status = BT_REBOOT;
					wait_count = 0;
				}
				break;
			default:
				break;
			}
		}else{
			TB05_USART("AT\r\n", sizeof("AT\r\n"));
			// USART_SendData(USART1, (uint8_t)ch);
		}
		break;
	case BT_ADV_TIME:
		wait_count++;
		if (wait_count > 1)
		{
			switch (respone_type)
			{
			case READY_RESPONE:
				tb05_status = BT_READY;
				printf("BT_READY\r\n");
			case ERROR_RESPONE:
			case BUSY_RESPONE:
				wait_count = 0;
				break;
			case OK_RESPONE:
				tb05_status = BT_RENAME;
				wait_count = 0;
				printf("BT_RENAME\r\n");
				break;
			case NONE_RESPONE:
				if (wait_count > TB05_MAX_RECV_TIMEOUT)
				{
					tb05_status = BT_REBOOT;
					wait_count = 0;
				}
				break;
			default:
				break;
			}
		}
		else
		{
			TB05_USART("AT+BLEADVINTV=160\r\n", sizeof("AT+BLEADVINTV=160\r\n"));
		}
		break;
	case BT_RENAME:
		wait_count++;
		if (wait_count > 1)
		{
			switch (respone_type)
			{
			case READY_RESPONE:
				tb05_status = BT_READY;
				printf("BT_READY\r\n");
			case ERROR_RESPONE:
			case BUSY_RESPONE:
				/*
					READY_RESPONE,
					BUSY_RESPONE,
					OK_RESPONE,
					ERROR_RESPONE,
					CONN_RESPONE,
					DISCONN_RESPONE,
				*/
				wait_count = 0;
				break;
			case OK_RESPONE:
				tb05_status = BT_ADV;
				wait_count = 0;
				printf("BT_ADV\r\n");
				break;
			case NONE_RESPONE:
				if (wait_count > TB05_MAX_RECV_TIMEOUT)
				{
					tb05_status = BT_REBOOT;
					wait_count = 0;
				}
				break;
			default:
				break;
			}
		}
		else
		{
			ChipID_Get(&chip_id);
			sprintf(ble_cmd, "AT+BLENAME=LoRa-BOARD-%08X\r\n", chip_id.ID_L);
			TB05_USART(ble_cmd, strlen(ble_cmd));
		}
		break;
	case BT_ADV:
		wait_count++;
		if (wait_count > 1)
		{
			switch (respone_type)
			{
			case READY_RESPONE:
				tb05_status = BT_CONNECTING;
				printf("BT_CONNECTING\r\n");
			case ERROR_RESPONE:
			case BUSY_RESPONE:
				/*
					READY_RESPONE,
					BUSY_RESPONE,
					OK_RESPONE,
					ERROR_RESPONE,
					CONN_RESPONE,
					DISCONN_RESPONE,
				*/
				wait_count = 0;
				break;
			case OK_RESPONE:
				tb05_status = BT_CONNECTING;
				wait_count = 0;
				printf("BT_CONNECTING\r\n");
				break;
			case NONE_RESPONE:
				if (wait_count > TB05_MAX_RECV_TIMEOUT)
				{
					tb05_status = BT_REBOOT;
					wait_count = 0;
				}
				break;
			default:
				if (wait_count > TB05_MAX_RECV_TIMEOUT)
				{
					tb05_status = BT_REBOOT;
					wait_count = 0;
				}
				break;
			}
		}
		else
		{
			TB05_USART("AT+BLEMODE=0\r\n", sizeof("AT+BLEMODE=0\r\n"));
		}
		break;
	case BT_DISCONN:
	case BT_CONNECTING:
		switch (respone_type)
		{
		case CONN_RESPONE:
			tb05_status = BT_TRANSPARENT;
			wait_count = 0;
			printf("BT_TRANSPARENT\r\n");
			break;
		default:
			break;
		}
		break;
	case BT_TRANSPARENT:
		switch (respone_type)
		{
		case READY_RESPONE:
			tb05_status = BT_READY;
			wait_count = 0;
			printf("BT_READY\r\n");
			break;
		case DISCONN_RESPONE:
			tb05_status = BT_DISCONN;
			wait_count = 0;
			printf("BT_DISCONN\r\n");
			break;
		default:
			break;
		}
		break;
	default:
		break;
	}
	if (BT_TRANSPARENT == tb05_status)
	{
		GPIO_SetBits(GPIOB, TB05_LED_PIN);
	}else if(BT_DISCONN == tb05_status || BT_CONNECTING == tb05_status ){
		// turn on led when BLE disconnect
		if (delay_count > 200)
		{
			GPIO_SetBits(GPIOB, TB05_LED_PIN);
			if (delay_count > 400)
				delay_count = 0;
		}
		else
		{
			GPIO_ResetBits(GPIOB, TB05_LED_PIN);
		}
	}else{
		GPIO_ResetBits(GPIOB, TB05_LED_PIN);
	}
	memset(ble_cmd,0,30);
	free(ble_cmd);
}

/* upload data to BLE master */
int tb05_radio_respone(const char *date, int dataLen)
{
	if (BT_TRANSPARENT == tb05_status)
	{
		char buffer[200] = {0};
		for (int i = 0; i < dataLen; i++)
		{
			buffer[i] = date[i];
		}
		// printf("send data to TB-05: %s\r\ndataLen:%d\r\n", buffer, dataLen);
		TB05_USART(buffer, dataLen);
		return 0;
	}else{
		return -1;
	}
}
