
#include "openssl_server_example.h"

#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "uart_control.h"
#include "lwip/err.h"
#include "lwip/sys.h"

#include "openssl/ssl.h"


#include "esp_event_loop.h"

#include "lwip/sockets.h"
#include "lwip/netdb.h"

#define AP_EXAMPLE "HTTP/1.1 200 OK\r\n" \
                                "Content-Type: text/html\r\n" \
                                "Content-Length: 98\r\n\r\n" \
                                "<html>\r\n" \
                                "<head>\r\n" \
                                "<title>OpenSSL example</title></head><body>\r\n" \
                                "AP Mode Example!\r\n" \
                                "</body>\r\n" \
                                "</html>\r\n" \
                                "\r\n"

/* The examples use WiFi configuration that you can set via 'make menuconfig'.

   If you'd rather not, just change the below entries to strings with
   the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
*/


#define EXAMPLE_ESP_WIFI_SSID      "DLINK"
#define EXAMPLE_ESP_WIFI_PASS      "DLINK1234"
#define EXAMPLE_MAX_STA_CONN       CONFIG_MAX_STA_CONN

static 	TaskHandle_t TaskHandle_AP;

int header_length = 0;

char _APbuffer[4000] = {0};
char temp_buff[500] = {0};

static int clientSock = -1;
bool wifi_available_flag = false;
bool AP_task = true;
int wifi_connect=0;
char REQUEST[2000];
char str[10] = "";
char ota_success_page[] = "<!DOCTYPE html><html><body><title>OTA Page Succes</title></head><body><h1> OTA Successful<br> File has been uploaded. The device will restart.</h1></body></html>";

const char send_data[] = AP_EXAMPLE;
const int send_bytes = sizeof(send_data);
char recv_buf[1024];

static EventGroupHandle_t wifi_event_group;


/* FreeRTOS event group to signal when we are connected*/
static EventGroupHandle_t s_wifi_event_group;

static const char *TAG = "wifi softAP";
const static int CONNECTED_BIT = BIT0;
int connect_bit=0;
static esp_err_t event_handler(void *ctx, system_event_t *event)
{

   	switch(event->event_id)
	{
	  case SYSTEM_EVENT_STA_START:
		esp_wifi_connect();
	       	break;
	  case SYSTEM_EVENT_STA_GOT_IP:

		printf("Connected to station\r\n");

		xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
		break;
	  case SYSTEM_EVENT_STA_DISCONNECTED:
		/* This is a workaround as ESP32 WiFi libs don't currently
		   auto-reassociate. */

		connect_bit=0;
		esp_wifi_connect();
		xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
		break;
       	  default:
	       	break;
      }
      return ESP_OK;
}

void wifi_init_softap()
{
s_wifi_event_group = xEventGroupCreate();
	char TEMP_BUF[100] ={0};
	tcpip_adapter_init();
	tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_AP) ;
	ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL) );
	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	ESP_ERROR_CHECK(esp_wifi_init(&cfg));
	tcpip_adapter_ip_info_t apinfo;
		tcpip_adapter_dns_info_t apdnsinfo;

	memset(TEMP_BUF, '\0', 20);
	sprintf(TEMP_BUF, "%d.%d.%d.%d", 192, 168, 4, 1);
	inet_pton(AF_INET, TEMP_BUF, &apdnsinfo.ip.u_addr.ip4);
	tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_AP,TCPIP_ADAPTER_DNS_MAIN, &apdnsinfo);
	//    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));

	wifi_config_t wifi_config = {
	.ap = {
		.ssid = EXAMPLE_ESP_WIFI_SSID,
		.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
		.password = EXAMPLE_ESP_WIFI_PASS,
		.max_connection = 4,
		.authmode = WIFI_AUTH_WPA_WPA2_PSK
	},
	};
	if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
	wifi_config.ap.authmode = WIFI_AUTH_OPEN;
	}

	ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
	ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config));
	ESP_ERROR_CHECK(esp_wifi_start());


	memset(TEMP_BUF, '\0', 20);
	sprintf(TEMP_BUF, "%d.%d.%d.%d", 192, 168, 4, 1);

	inet_pton(AF_INET, TEMP_BUF, &apinfo.ip);							//Sets the IP Address of the AP Mode
	memset(TEMP_BUF, '\0', 20);
	sprintf(TEMP_BUF, "%d.%d.%d.%d", 192, 168, 4, 0);
	inet_pton(AF_INET, TEMP_BUF, &apinfo.gw);							//Sets the Gateway IP of the AP Mode

	memset(TEMP_BUF, '\0', 20);
	sprintf(TEMP_BUF, "%d.%d.%d.%d", 255, 255, 255, 0);
	inet_pton(AF_INET, TEMP_BUF, &apinfo.netmask);							//Sets the Subnet Mask of the AP Mode
	tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &apinfo);					//Stores all the configuration on TCP/IP Adapter


	tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_AP) ;
	vTaskDelay(2000 / portTICK_PERIOD_MS);
	tcpip_adapter_ip_info_t ip;

	memset(&ip, 0, sizeof(tcpip_adapter_ip_info_t));

	if (tcpip_adapter_get_ip_info(ESP_IF_WIFI_AP, &ip) == 0)
	{


		ESP_LOGI(TAG, "~~~~~~AP~~~~~");
		ESP_LOGI(TAG, "IP:"IPSTR, IP2STR(&ip.ip));
		ESP_LOGI(TAG, "MASK:"IPSTR, IP2STR(&ip.netmask));
		ESP_LOGI(TAG, "GW:"IPSTR, IP2STR(&ip.gw));
		ESP_LOGI(TAG, "~~~~~~AP~~~~~");



	}
	wifi_connect=1;

}

void client_task(void *pv)
{
	int ret;
  	clientSock = (int)pv;
  	memset(temp_buff,0,sizeof(temp_buff));
	memset(_APbuffer,0,sizeof(_APbuffer));

	do{
		read(clientSock, temp_buff, 1);
		_APbuffer[header_length++] = temp_buff[0];

//		serial_write(UART_NUM_0, temp_buff[0]);

		if((_APbuffer[header_length - 1] == '\n') && (_APbuffer[header_length - 2] == '\r') && (_APbuffer[header_length - 3] == '\n') && (_APbuffer[header_length - 4] == '\r'))
		{
			break;
		}
	//	vTaskDelay(100);

	}while(1);

//	printf("DATA:%s\n\n",_APbuffer);
	_APbuffer[header_length] = '\0';
	 if (strstr(_APbuffer, "GET ") &&strstr(_APbuffer, " HTTP/1.1"))
	 {
	  	            ESP_LOGI(TAG, "Got the message");
	  	            ESP_LOGI(TAG, "Message Write");
	  	            ret = write(clientSock, send_data, send_bytes);
	  	            if (ret > 0) {
	  	                ESP_LOGI(TAG, "OK");
	  	            } else {
	  	                ESP_LOGI(TAG, "error");
	  	            }
	 }
	 header_length = 0;

    close(clientSock);
    vTaskDelete(NULL);


}




/*FreeRTOS Task to Create the AP server and waits for the client to connect.
	Parameters : void *pvParameters : parameters
	Return 	   : void
*/
void AP_socket_task(void *pvParameters)
{


	int sock;
	while(!wifi_connect)
	{
		vTaskDelay(10/portTICK_PERIOD_MS);
	}
	printf("AP_socket_task start\r\n");
	struct sockaddr_in clientAddress;								//To Hold the Client Address

	struct sockaddr_in serverAddress;								//To Hold the Server Address
	//int option =1;
	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);						//Create the server
	if (sock < 0) {
		ESP_LOGE(TAG, "socket: %d %s", sock, strerror(errno));
	}
	memset( &serverAddress,'\0',sizeof(serverAddress));
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddress.sin_port = htons(80);
	int rc  = bind(sock, (struct sockaddr *)&serverAddress, sizeof(serverAddress));		    	//Bind the Server IP address and port to the Socket.
	if (rc < 0) {
		ESP_LOGE(TAG, "bind: %d %s", rc, strerror(errno));

	}
	rc = listen(sock, 100);//set the number of waiting connection
	if (rc < 0) {
		ESP_LOGE(TAG, "listen: %d %s", rc, strerror(errno));

	}

	while (1)
	{
		printf("IN AP\n");

		// Listen for a new client connection.
		socklen_t clientAddressLength = sizeof(clientAddress);
		int clientSock = accept(sock, (struct sockaddr *)&clientAddress, &clientAddressLength);//Wait for the client to connect to the Server.


		if (clientSock < 0)
		{
			ESP_LOGE(TAG, "accept: %d %s (%d)", clientSock, strerror(errno),errno);

		}
		printf("before client task\r\n");
		xTaskCreate(&client_task,"client_task",16384,(void *)clientSock, 6, NULL);		//Client task is created
	}
	printf("before task delete AP_socket_task\r\n");
}


void app_main()
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ESP_LOGI(TAG, "ESP_WIFI_MODE_AP");
	serial_begin(UART_NUM_0, 115200, 1 ,  3 );

    xTaskCreate(&AP_socket_task, "AP socket_task", 8192, NULL, 5, &TaskHandle_AP);

    wifi_init_softap();

}















