#include "ESP8266.h"
#include "USART.h"

ESP_flags ESP_Flags = {0};
ESP_Answer ESP_LastAnswer = ESP_Nothing;
ESP_StrFinderDesc ESP_StaticStrs = {0};

uint8_t ESP_BufferIndex = 0;
uint8_t ESP_Buffer[ESP_BufferSize];

uint16_t ESP_SearchIndex = 0;

uint8_t  ESP_ReceiveData[ESP_ReceiveBufferSize];
uint16_t ESP_ReceiveData_Index = 0;

const char ESP_Answer_OK[]   		= "OK\r";
const char ESP_Answer_Fail[] 		= "Fail\r";
const char ESP_Answer_Error[] 		= "ERROR\r";
const char ESP_Answer_Diconnected[] = "WIFI DISCONNECT\r";
const char ESP_Answer_Connected[] 	= "WIFI CONNECTED\r";
const char ESP_Answer_ReceiveData[] = "+IPD,";
const char ESP_Answer_GotIP[] 		= "WIFI GOT IP\r";
const char ESP_Answer_TCP_Connect[] = "CONNECT\r";
const char ESP_Answer_TCP_Close[]   = "CLOSE\r";

void ESP_Init(void)
{
	//set ESP_StaticStrs
	// ESP_Ok == 0
	ESP_StaticStrs.Strs[ESP_Ok] = ESP_Answer_OK;
	// ESP_Fail == 1
	ESP_StaticStrs.Strs[ESP_Fail] = ESP_Answer_Fail;
	// ESP_Error  == 2
	ESP_StaticStrs.Strs[ESP_Error] = ESP_Answer_Error;
	// ESP_Disconncted == 3
	ESP_StaticStrs.Strs[ESP_Disconnected] = ESP_Answer_Diconnected;
	// ESP_Connected == 4
	ESP_StaticStrs.Strs[ESP_Connected] = ESP_Answer_Connected;
	// ESP_ReceiveData == 5
	ESP_StaticStrs.Strs[ESP_ReceiveDataAnswer] = ESP_Answer_ReceiveData;
	// ESP_GotIP == 6
	ESP_StaticStrs.Strs[ESP_GotIP] = ESP_Answer_GotIP;
	// ESP_TCPConnect == 7
	ESP_StaticStrs.Strs[ESP_TCP_Connect] = ESP_Answer_TCP_Connect;
	// ESP_TCPClose == 8
	ESP_StaticStrs.Strs[ESP_TCP_Close] = ESP_Answer_TCP_Close;
	// Length == sum of all messsages
	ESP_StaticStrs.Length = ESP_NumOfAnswers;
}
void ESP_AppendChar(char c){
    ESP_Buffer[ESP_BufferIndex++] = c;
    if (ESP_BufferIndex >= ESP_BufferSize){
        ESP_BufferIndex = 0;
    }
}
void ESP_Check(void)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_Echo(uint8_t State)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("ATE");
	ESP_Sendn(State);
	ESP_Sends("\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_Restart(void)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+RST\r\n");
	ESP_Flags.WaitingForAnswer = 1;
}
void ESP_WiFiMode(uint8_t Mode)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CWMODE=");
	ESP_Sendn(Mode);
	ESP_Sends("\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_Disconnect(void)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CWQAP\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_Connect(char* SSID, char* Password)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CWJAP=\"");
	ESP_Sends(SSID);
	ESP_Sends("\",\"");
	ESP_Sends(Password);
	ESP_Sends("\"\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_setAccessPoint(char* SSID, char* Password)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CWSAP=\"");
	ESP_Sends(SSID);
	ESP_Sends("\",\"");
	ESP_Sends(Password);
	ESP_Sends("\",1,");
	//no password ?
	if(Password[0] == '\0')
		ESP_Sends("0\r\n");
	else
		ESP_Sends("3\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_setMAC_Station(char* MAC)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPSTAMAC=\"");
	ESP_Sends(MAC);
	ESP_Sends("\"\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_setMAC_AccessPoint(char* MAC)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPAPMAC=\"");
	ESP_Sends(MAC);
	ESP_Sends("\"\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_setIP_Station(char* IP)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPSTA=\"");
	ESP_Sends(IP);
	ESP_Sends("\"\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_setIP_AccessPoint(char* IP)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPAP=\"");
	ESP_Sends(IP);
	ESP_Sends("\"\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_TCPConnect(char* RemoteIP,uint16_t RemotePort)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPSTART=");
	ESP_Sends("\"TCP\",\"");
	ESP_Sends(RemoteIP);
	ESP_Sends("\",");
	ESP_Sendn(RemotePort);
	ESP_Sends("\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_TCPSendData(uint8_t* Data, uint16_t Length)
{
	uint16_t i;
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPSEND=");
	ESP_Sendn(Length);
	ESP_Sends("\r\n");
	//waiting for "> " (two chars)
	for(i=0; i < 7000 ;i++);
	ESP_SendData(Data,Length);
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);//for OK
	ESP_LastAnswer = ESP_Nothing;
	while(ESP_LastAnswer == ESP_Nothing);//for SEND OK
	#endif //ESP_Delay
}
void ESP_TCPClose(void)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPCLOSE\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_MultiConnection(uint8_t State)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPMUX=");
	ESP_Sendn(State);
	ESP_Sends("\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_TCPServer(uint16_t Port)
{
	ESP_SearchIndex = ESP_BufferIndex;
	ESP_LastAnswer = ESP_Nothing;
	ESP_Sends("AT+CIPSERVER=1,\"");
	ESP_Sendn(Port);
	ESP_Sends("\"\r\n");
	ESP_Flags.WaitingForAnswer = 1;
	#ifdef ESP_Delay
	while(ESP_LastAnswer == ESP_Nothing);
	#endif //ESP_Delay
}
void ESP_ReleaseReceiveBuffer(void)
{
	ESP_BufferIndex = 0;         
    ESP_ReceiveData_Index = 0;
	ESP_Flags.DataReceived = 0;
}
//tools function
uint8_t strcomp(flash const char* src,char* dest){
	while(*src !='\0'){
		if(*src++ != *dest++)
			return 0;
	}
	return 1;
}
int16_t strchar(char* src, char c, uint16_t top)
{
	uint16_t index = 0;
	while(src != '\0' && index < top){
		if(src[index++] == c)
			return index - 1;
	}
	return -1;
}
void strget(char* src, char* dest, uint16_t start, uint16_t end)
{
	uint16_t i = 0;
	while(start < end){
		dest[i++] = src[start++];
	}
	dest[i] = '\0';
}
int8_t strgetc(char* src, char* dest, char start, char end)
{
	int16_t A,B;
	A = strchar(src, start, 0xff);//0xff for too long string
	if(A != -1){
		B = strchar(&src[A+1], end, 0xff);
		if(B != -1){
			strget(src, dest, A+1, A+B+1);
			return 1;
		}
		else{
			return -2;
		}
	}
	else{
		return -1;//can't finde start char
	}
}
uint16_t strtonum(char* str)
{
	uint16_t z = 0;
	while(*str != '\0'){
		if(*str <= '9' && *str >= '0')
			z = (z * 10) + ( *str - 0x30);
		else
			break;
		str++;
	}
	return z;
}
uint16_t strlength(char* str)
{
	uint16_t i;
	for(i=0;str[i] != '\0';i++);
	return i;
}
void readdata(uint8_t* src, uint8_t* buff, uint16_t size)
{
	while(size > 0){
		*buff++ = *src++;
		size--;
	}
}
ESP_Answer AnswerFinder(void)
{
	//nothing == 0xff
	ESP_Answer answer = ESP_Nothing;
	uint16_t index;
	uint8_t AnswerLength;
	char length[5];
	uint16_t datasize = 0;
	uint16_t i;
	for(index = ESP_SearchIndex; index < ESP_BufferIndex ; index++){
		for(i=0; i<ESP_StaticStrs.Length;i++){
			if(ESP_StaticStrs.Strs[i][0] == ESP_Buffer[index]){
				if(strcomp(ESP_StaticStrs.Strs[i],(char*)&ESP_Buffer[index])){
					//check is data?
					if(i == ESP_ReceiveDataAnswer){
						ESP_Flags.DataReceiving = 1;
						if(strchar((char*)&ESP_Buffer[index], ':', ESP_BufferIndex - index + 1) != -1){
							// get data length
							if(ESP_Flags.MultiConnection){

							}
							else{
								if(strgetc((char*)&ESP_Buffer[index], length, ',', ':') == 1){
									AnswerLength = 6 + strlength(length);
									datasize = strtonum(length);
									//check all data recived?
									if((ESP_BufferIndex - (index + AnswerLength)) >= datasize){
										//get all data
										readdata(&ESP_Buffer[index + AnswerLength ], &ESP_ReceiveData[ESP_ReceiveData_Index], datasize);
										ESP_ReceiveData_Index +=  datasize;
										ESP_Flags.DataReceived = 1;
										ESP_Flags.DataReceiving = 0;
										//remove past answer
										ESP_SearchIndex = index + AnswerLength + datasize + 1;
									}
								}
							}
						}
					}
					else{
						//remove past answer
						ESP_SearchIndex = index + 1;
					}
					//i == answer type
					return (ESP_Answer)i;
				}
			}
		}
	}
	return answer;
}
void ESP_CheckAnswer(void)
{
    switch(AnswerFinder())
    {
        case ESP_Nothing: // 0xff
            ESP_LastAnswer = ESP_Nothing;
            break;
        case ESP_Ok: 			// 0
            ESP_LastAnswer = ESP_Ok;
            ESP_Flags.WaitingForAnswer = 0;
            ESP_Flags.Answer_Received = 1;
            ESP_BufferIndex = 0;
            ESP_SearchIndex = 0;
            break;
        case ESP_Fail: 		// 1
            ESP_LastAnswer = ESP_Fail;
            ESP_Flags.WaitingForAnswer = 0;
            ESP_Flags.Answer_Received = 1;
            ESP_BufferIndex = 0;
            ESP_SearchIndex = 0;
            break;
        case ESP_Error:		// 2
            ESP_LastAnswer = ESP_Error;
            ESP_Flags.WaitingForAnswer = 0;
            ESP_Flags.Answer_Received = 1;
            ESP_BufferIndex = 0;
            ESP_SearchIndex = 0;
            break;
        case ESP_Disconnected: // 3
            ESP_Flags.WIFI_Connected = 0;
            ESP_Flags.Answer_Received = 1;
            break;
        case ESP_Connected: // 4
            ESP_Flags.WIFI_Connected = 1;
            ESP_Flags.Answer_Received = 1;
            break;
        case ESP_ReceiveDataAnswer: // 5

            break;
        case ESP_GotIP: // 6
            ESP_Flags.WIFI_GotIP = 1;
            ESP_Flags.Answer_Received = 1;
            break;
        case ESP_TCP_Connect: // 7
            ESP_Flags.TCPConnected = 1;
            break;
        case ESP_TCP_Close: // 8
            ESP_Flags.TCPConnected = 0;
            break;
    }
}

