#include <stdio.h>
#include <string.h>
#include "../mcu/types.h"
#include "../mcu/serial.h"
#include "../mcu/delay.h"
#include "../util/util.h"
#include "../util/sockutil.h"
#include "../util/myprintf.h"
#include "../iinchip/socket.h"
#include "../iinchip/w5100.h"
#include "../inet/httpd.h"
#include "../rom/searchfile.h"
#include "../evb/channel.h"
#include "../evb/evb.h"
#include "../evb/led.h"
#include "../evb/config.h"
#include "../main/main.h"

#include "webserver.h"

//#define WEB_DEBUG
char* http_response;		// Pointer to HTTP response
st_http_request *http_request;	// Pointer to HTTP request

char data_buf1[TX_RX_MAX_BUF_SIZE] = {0};
char data_buf2[TX_RX_MAX_BUF_SIZE] = {0};

u_int replace_sys_env_value(char* base,u_int len);	// Replace HTML's variables to system configuration value

/* http service */
void proc_http(SOCKET, u_char *, int);		// processing HTTP

void web_server(u_char ch)
{
	int len;
	u_int wait_send=0;
	
	http_request = (st_http_request*)data_buf1;		// struct of http request
	
	/* http service start */
	switch(getSn_SR(ch))
	{
	case SOCK_ESTABLISHED:	
		if(bchannel_start[ch]==1)
		{
			printf("%d : Connected by %s(%u)\r\n",ch,inet_ntoa(GetDestAddr(ch)),GetDestPort(ch));
			bchannel_start[ch] = 2;
		}
		if ((len = getSn_RX_RSR(ch)) > 0)		
		{
			if ((u_int)len > MAX_URI_SIZE) len = MAX_URI_SIZE;				
			len = recv(ch, (u_char*)http_request, len);
			*(((u_char*)http_request)+len) = 0;
#ifdef WEB_DEBUG				
			printf( "- HTTP REQUEST -\r\n");
#endif
			proc_http(ch, (u_char*)http_request, len);	// request is processed
			while(getSn_TX_FSR(ch) != getIINCHIP_TxMAX(ch))
			{
				if(wait_send++ > 1500)
				{
#ifdef WEB_DEBUG
					printf( "HTTP Response send fail\r\n");
#endif
					break;
				}
				wait_1ms(1);
			}
			disconnect(ch);
		}
		break;
	case SOCK_CLOSE_WAIT:   
#ifdef WEB_DEBUG	
		printf("CLOSE_WAIT : %d\r\n",ch);	// if a peer requests to close the current connection
#endif		
		disconnect(ch);
		bchannel_start[ch] = 0;
	case SOCK_CLOSED:                   
		if(!bchannel_start[ch])
		{
			printf("%d : Web Server Started.\r\n",ch);
			bchannel_start[ch] = 1;
		}
		if(socket(ch,Sn_MR_TCP,ChConf.ch[ch].port,0x00) == 0)    /* reinitialize the socket */
		{
			printf("\a%d : Fail to create socket.\r\n",ch);
			bchannel_start[ch] = 0;
		}
		else	listen(ch);
		break;
	}	// end of switch 
}

void proc_http(SOCKET s, u_char * buf, int length)
{
	char * content;
	char name[MAX_URI_SIZE] = {0,};
	char * param;
	u_int file_len;
	u_int send_len;

	http_request = (st_http_request*)data_buf2;		// struct of http request
	http_response = (char*)data_buf1;			// buffer for response header 

	parse_http_request(http_request, buf);			// After analyze request, convert into http_request
	
	/* method Analyze */
	switch (http_request->METHOD)				
	{
	case METHOD_ERR :					
		send(s, (u_char *)ERROR_REQUEST_PAGE, strlen(ERROR_HTML_PAGE));
		break;
	case METHOD_HEAD:
	case METHOD_GET :
	case METHOD_POST :
		strcpy(name, get_http_uri_name(http_request->URI));
		if (!strcmp(name, "/")) strcpy(name,"index.html");	// If URI is "/", respond by index.htm 
#ifdef WEB_DEBUG
		if(strlen(name)	< 80)	printf("PAGE : %s\r\n", name);
		else printf("TOO LONG FILENAME\r\n");
#endif 			
		find_http_uri_type(&http_request->TYPE, name);	//Check file type (HTML, TEXT, GIF, JPEG are included)
#ifdef WEB_DEBUG			
		PRINTLN("find_type() ok");
#endif		
		if(http_request->TYPE == PTYPE_CGI)
		{
			if(strstr(name,"NETCONFIG.CGI"))
			{
				if((param = get_http_param_value(http_request->URI,"sip")))
					NetConf.sip= htonl(inet_addr(param));
				if((param = get_http_param_value(http_request->URI,"gwip")))
					NetConf.gwip= htonl(inet_addr(param));
				if((param = get_http_param_value(http_request->URI,"sn")))
					NetConf.sn= htonl(inet_addr(param));
				if((param = get_http_param_value(http_request->URI,"dns")))
					NetConf.dns= htonl(inet_addr(param));
				set_netconf(&NetConf);
				send(s, (u_char *)RETURN_CGI_PAGE, strlen(RETURN_CGI_PAGE));	
				evb_soft_reset();
				return;
			}
			else if(strstr(name,"LCDNLED.CGI"))
			{
				if((param = get_http_param_value(http_request->URI,"lcd")))
				{
					if( (*param == 'l') && (*(param + 1) == 'e') && (*(param + 2) == 'd') && (*(param + 4) == '=') )
					{
						evb_set_lcd_text(1,"                ");
					}
					else
					{
						*(param+16) = 0;
						evb_set_lcd_text(1,param);
					}
				}
				if((param = get_http_param_value(http_request->URI,"led0")))
				{
					if(!strcmp(param,"on")) led_on(0);
					else			led_off(0);
				}
				else	led_off(0);
				if((param = get_http_param_value(http_request->URI,"led1")))
				{
					if(!strcmp(param,"on"))	led_on(1);
					else			led_off(1);
				}
				else	led_off(1);
				strcpy(name,"evbctrl.html");
				find_http_uri_type(&http_request->TYPE, name);
			}
		}
		
		/* Search the specified file in stored binaray html image */
		if (!search_file(name, &content, &file_len))		//if the file do not exist then
		{
			send(s, (u_char *)ERROR_HTML_PAGE, strlen(ERROR_HTML_PAGE));	
#ifdef WEB_DEBUG				
			printf("Unknown Page\r\n");
#endif				
		} 
		else 						// if search file sucess 
		{
			
#ifdef WEB_DEBUG				
			printf("find file ok\r\n");
#endif				
			make_http_response_head(http_response, http_request->TYPE, (u_long)file_len);			
			send(s, (u_char*)http_response, strlen(http_response));
			while (file_len) 
			{
				if (file_len >= TX_RX_MAX_BUF_SIZE-1)
					send_len = TX_RX_MAX_BUF_SIZE-1;
				else	send_len = file_len;
				memcpy(http_response, content, send_len);
				*(http_response+send_len+1) = 0;
				// Replace htmls' system environment value to real value
				if(http_request->TYPE==PTYPE_HTML)
					send_len = replace_sys_env_value(http_response,send_len);
				send(s, (u_char*)http_response, send_len);
				content += send_len;
				file_len -= send_len;
			}
        	}
		break;
	default :
		break;
	}
}

u_int replace_sys_env_value(char* base, u_int len)
{
	char str[18];	
	char *ptr,*tptr;
	
	tptr = ptr = base;

	while((ptr=strchr(tptr,'$')))
	{
		if((tptr=strstr(ptr,EVB_NET_SIP)))
		{
			DPRINTLN("REPLACE SIP");			
			memcpy(tptr,inet_ntoa_pad(ntohl(NetConf.sip)),15);
			tptr+=15;
		}
		else if((tptr=strstr(ptr,EVB_NET_GWIP)))
		{
			DPRINTLN("REPLACE GWIP");
			memcpy(tptr,inet_ntoa_pad(ntohl(NetConf.gwip)),15);
			tptr+=15;
		}
		else if((tptr=strstr(ptr,EVB_NET_SN)))
		{
			DPRINTLN("REPLACE SN");
			memcpy(tptr,inet_ntoa_pad(ntohl(NetConf.sn)),15);
			tptr+=15;
		}
		else if((tptr=strstr(ptr,EVB_NET_DNS)))
		{
			DPRINTLN("REPLACE DNS");
			memcpy(tptr,inet_ntoa_pad(ntohl(NetConf.dns)),15);
			tptr+=15;
		}
		else if((tptr=strstr(ptr,EVB_NET_MAC)))
		{
			DPRINTLN("REPLACE MAC ADDRESS");
			sprintf(str,"%02X.%02X.",NetConf.mac[0],NetConf.mac[1]);
			sprintf(str+6,"%02X.%02X.",NetConf.mac[2],NetConf.mac[3]);
			sprintf(str+12,"%02X.%02X",NetConf.mac[4],NetConf.mac[5]);
			memcpy(tptr,str,17);
			tptr+=17;
		}
		else if((tptr=strstr(ptr,EVB_LCD_TEXT)))
		{
			DPRINTLN("REPLACE LCD TEXT");
			memset(tptr,0x20,16);
			memcpy(tptr,evb_get_lcd_text(1),16);
			tptr+=16;
		}
		else if((tptr=strstr(ptr,EVB_LED0_STAT)))
		{
			DPRINTLN("REPLACE LED0 STAT");
			memset(tptr,0x20,7);
			if(led_state(0)==LED_ON) memcpy(tptr,"checked",7);
			tptr+=7;
		}
		else if((tptr=strstr(ptr,EVB_LED0_IMG)))
		{
			DPRINTLN("REPLACE LED0 IMG");
			memset(tptr,0,10);
			if(led_state(0)==LED_ON) memcpy(tptr,"led_on.gif",10);
			else			 memcpy(tptr,"led_of.gif",10);
			tptr+=10;
		}
		else if((tptr=strstr(ptr,EVB_LED1_STAT)))
		{
			DPRINTLN("REPLACE LED1 STAT");
			memset(tptr,0x20,7);
			if(led_state(1)==LED_ON) memcpy(tptr,"checked",7);
			tptr+=7;
		}
		else if((tptr=strstr(ptr,EVB_LED1_IMG)))
		{
			DPRINTLN("REPLACE LED1 IMG");
			memset(tptr,0,10);
			if(led_state(1)==LED_ON) memcpy(tptr,"led_on.gif",10);
			else			 memcpy(tptr,"led_of.gif",10);
			tptr+=10;
		}
		else	// tptr == 0 && ptr!=0;
		{
			if(ptr==base)
			{
				DPRINTLN("$ Charater");
				return len;
			}
			DPRINTLN("REPLACE CONTINUE");
			tptr = ptr;
			break;
		}
	}
	if(!ptr) return len;
	return (u_int)(tptr-base);
}
