//*****************************************************************************
//
//! @file
//! @brief HTTP configure
//
//*****************************************************************************

// STELARISWARE
#include "string.h"
#include "utils/lwiplib.h"
#include "httpserver_raw/httpd.h"
#include "utils/ustdlib.h"
#include "lwip/inet.h"

// PROJECT INCLUDES
#include "../myutils/uartstdio.h"
#include "../sniffer.h"
#include "http_conf.h"
#include "cgifuncs.h"
#include "../radio/at86rf231.h"
#include "../radio/at86rf212.h"

//******************************************************************************

tSnifferSettings *ptrSnifferSettings;

unsigned char ED_scan[27];

//******************************************************************************

void HttpdInit(tSnifferSettings *ptr) {
    ptrSnifferSettings = ptr;
    http_set_ssi_handler(SSIHandler, g_pcConfigSSITags,NUM_CONFIG_SSI_TAGS);
    http_set_cgi_handlers(g_psConfigCGIURIs, NUM_CONFIG_CGI_URIS);
    httpd_init();
}

//******************************************************************************

void DisplayIPAddress(unsigned long ipaddr, unsigned long ulCol, unsigned long ulRow)
{
    char pucBuf[16];
    unsigned char *pucTemp = (unsigned char *)&ipaddr;

    //
    // Convert the IP Address into a string.
    //
    usprintf(pucBuf, "%d.%d.%d.%d", pucTemp[0], pucTemp[1], pucTemp[2], pucTemp[3]);
}

//*****************************************************************************
//
// Required by lwIP library to support any host-related timer functions.
//
//*****************************************************************************
void lwIPHostTimerHandler(void)
{
    static unsigned long ulLastIPAddress = 0;
    unsigned long ulIPAddress;

    ulIPAddress = lwIPLocalIPAddrGet();

	//
    // Check if IP address has changed, and display if it has.
    //
    if(ulLastIPAddress != ulIPAddress)
    {
        ulLastIPAddress = ulIPAddress;
        DisplayIPAddress(ulIPAddress, 36, 16);
        ulIPAddress = lwIPLocalNetMaskGet();
        DisplayIPAddress(ulIPAddress, 36, 24);
        ulIPAddress = lwIPLocalGWAddrGet();
        DisplayIPAddress(ulIPAddress, 36, 32);
    }
}

//*****************************************************************************
//
// SSIHandler
//
//*****************************************************************************
int SSIHandler(int iIndex, char *pcInsert, int iInsertLen)
{
    
    if(iIndex == SSI_INDEX_CHN_LOW)  //edch0
    {
      
      
              //Disable interrupt from radio
              Trx_IntDisable();
              
              
              switch(ptrSnifferSettings->radio)
              {
              case TRX212:
                {
                          
                    if((trx212_ED_Scan((unsigned char*)&ED_scan,
                                       ptrSnifferSettings->channel,RUNNING)==false) || 
                       (trx231_ED_Scan((unsigned char*)&ED_scan,11,STOPPED)==false))
                        ptrSnifferSettings->state=ERROR;
                    
                    break; 
                }
                      
              case TRX231:
                {
                          
                    if((trx212_ED_Scan((unsigned char*)&ED_scan,0,STOPPED)==false) || 
                       (trx231_ED_Scan((unsigned char*)&ED_scan, 
                                       ptrSnifferSettings->channel,RUNNING)==false))
                        ptrSnifferSettings->state=ERROR;
                    
                    break;
                }    
              }
              
              
              //Enable interrupt from radio              
              
              Trx_IntEnable();
            
              if(ED_scan[0]==0)usnprintf(pcInsert, iInsertLen,"<-91"); 
              else if(ED_scan[0]<=0x54)
                usnprintf(pcInsert, iInsertLen,"%d",(-91+ED_scan[0]));
              else usnprintf(pcInsert, iInsertLen,"Reset value");

    }   
    else if((iIndex > SSI_INDEX_CHN_LOW) && (iIndex <= SSI_INDEX_CHN_HIGH))  //edch1-26 	
    {
                    
            if(ED_scan[iIndex - SSI_INDEX_CHN_LOW]==0)usnprintf(pcInsert, iInsertLen,"<-91"); 
            else if(ED_scan[iIndex - SSI_INDEX_CHN_LOW]<=0x54)
              usnprintf(pcInsert, iInsertLen,"%d",(-91+ED_scan[iIndex - SSI_INDEX_CHN_LOW]));
            else usnprintf(pcInsert, iInsertLen,"Reset value");

    }  
    else     //other values 
    {
    switch(iIndex)
    {
      
        case SSI_INDEX_P_THR:
          usnprintf(pcInsert, iInsertLen,"%d",g_PacketCount);          
        break;  
        
        case SSI_INDEX_P_DROP:
          usnprintf(pcInsert, iInsertLen,"%d",g_PacketDrop);          
        break;
        
        case SSI_INDEX_REDIR:
          
          usnprintf(pcInsert, iInsertLen,  "%d.%d.%d.%d", ptrSnifferSettings->ipaddr[0],
                    ptrSnifferSettings->ipaddr[1], 
                    ptrSnifferSettings->ipaddr[2], 
                    ptrSnifferSettings->ipaddr[3]);  
          
          
          ptrSnifferSettings->setIpConfig=true;
          
          
          break;
      
    	case SSI_INDEX_STATE:
    		switch(ptrSnifferSettings->state)
    		{
    			case RUNNING:
    				usnprintf(pcInsert, iInsertLen,"RUNNING");
    			break;
    			case STOPPED:
    				usnprintf(pcInsert, iInsertLen,"STOPPED");
    			break;
    			case ERROR:
    				usnprintf(pcInsert, iInsertLen,"ERROR");
    			break;
    		}  	
    	break;
    	
    	case SSI_INDEX_IPADDR:
    		usnprintf(pcInsert, iInsertLen,  "%d.%d.%d.%d", ptrSnifferSettings->ipaddr[0],
    														ptrSnifferSettings->ipaddr[1], 
    														ptrSnifferSettings->ipaddr[2], 
    														ptrSnifferSettings->ipaddr[3]);
    	break;
    	
    	case SSI_INDEX_NMASK:
    		usnprintf(pcInsert, iInsertLen,  "%d.%d.%d.%d", ptrSnifferSettings->nmask[0],
    														ptrSnifferSettings->nmask[1], 
    														ptrSnifferSettings->nmask[2], 
    														ptrSnifferSettings->nmask[3]);
    	break;
    	
    	case SSI_INDEX_GW:
    		usnprintf(pcInsert, iInsertLen,  "%d.%d.%d.%d", ptrSnifferSettings->gw[0],
    														ptrSnifferSettings->gw[1], 
    														ptrSnifferSettings->gw[2], 
    														ptrSnifferSettings->gw[3]);
    	break;
    	
    	case SSI_INDEX_MACADDR:
    		usnprintf(pcInsert, iInsertLen,  "%02X-%02X-%02X-%02X-%02X-%02X", 
    		ptrSnifferSettings->macaddr[0],
    		ptrSnifferSettings->macaddr[1],
    		ptrSnifferSettings->macaddr[2],
    		ptrSnifferSettings->macaddr[3],
    		ptrSnifferSettings->macaddr[4],
    		ptrSnifferSettings->macaddr[5]);
    	break;
    	
    	case SSI_INDEX_CHANNEL:
    		usnprintf(pcInsert, iInsertLen,"%d", ptrSnifferSettings->channel);
    	break;
    	
    	case SSI_INDEX_SENSITIVITY:
    		switch(ptrSnifferSettings->sensitivity)
    		{
    			case HIGH:
    				usnprintf(pcInsert, iInsertLen,"High");
    			break;
    			case MEDIUM:
    				usnprintf(pcInsert, iInsertLen,"Medium");
    			break;
    			case LOW:
    				usnprintf(pcInsert, iInsertLen,"Low");
    			break;
    			case LOWEST:
    				usnprintf(pcInsert, iInsertLen,"Lowest");
    			break;
    		}

    	break;
    	
    	case SSI_INDEX_PANFILTER:
    		usnprintf(pcInsert, iInsertLen,"0x%02X%02X", ptrSnifferSettings->filterPanId[0], ptrSnifferSettings->filterPanId[1]);
    	break;
    	
    	case SSI_INDEX_CRCFILTER:
    		usnprintf(pcInsert, iInsertLen, (ptrSnifferSettings->filterCrc) ? "ON" : "OFF");
    	break;
        
        case SSI_INDEX_REIPPADDR:
    		usnprintf(pcInsert, iInsertLen,  "%d.%d.%d.%d",
                          ptrSnifferSettings->reipaddr[0],
                          ptrSnifferSettings->reipaddr[1], 
    			  ptrSnifferSettings->reipaddr[2], 
    		          ptrSnifferSettings->reipaddr[3]);
    	break;
        
        case  SSI_INDEX_REPORT:
    		usnprintf(pcInsert, iInsertLen,"%d", ptrSnifferSettings->report);
    	break; 
                
        case  SSI_INDEX_CHN:
    		usnprintf(pcInsert, iInsertLen,"ch%d", ptrSnifferSettings->channel);
    	break;  
            	
        case SSI_INDEX_DHCP:
    		usnprintf(pcInsert, iInsertLen, (ptrSnifferSettings->dhcpOn) ? "ON" : "OFF");
    	break;
                
    
    }
	
    }
    
    return(strlen(pcInsert));
} 

//******************************************************************************


char *StatusCGIHandler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{
   long status;
   char pcDecodedString[32];	
   status = FindCGIParameter("status", pcParam, iNumParams);
   
   if(status == -1) return(PARAM_ERROR_RESPONSE);
   
   // toggle sniffer RUNNING/STOP
   DecodeFormString(pcValue[status], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if(strcmp(pcDecodedString,"toogle"))
       return(PARAM_ERROR_RESPONSE);
   
   
   if(ptrSnifferSettings->state == RUNNING)
   {
     
       if(Trx_STOP()==false)
         ptrSnifferSettings->state=ERROR;
       else ptrSnifferSettings->state=STOPPED; 
     
   }
   else if(ptrSnifferSettings->state ==STOPPED)
   {

     if(Trx_RUN()==false)
         ptrSnifferSettings->state=ERROR; 
     else ptrSnifferSettings->state=RUNNING;     
   
   }
   
   
   return(DEFAULT_CGI_RESPONSE);
}

//******************************************************************************

//http://10.10.10.2/settings.cgi?chn=ch0&rxsens=highest&panfilter=none
char *SettingsCGIHandler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{  
   long chn, rxsens, panfilter, crcfilter;
   char pcDecodedString[32];
   tBoolean tempCrc;
   
   tSnifferSensitivity tempSens;
   	
   chn = FindCGIParameter("chn", pcParam, iNumParams);
   rxsens = FindCGIParameter("rxsens", pcParam, iNumParams);
   panfilter = FindCGIParameter("panfilter", pcParam, iNumParams);
   crcfilter = FindCGIParameter("crcfilter", pcParam, iNumParams);

   if((chn == -1) || (rxsens == -1) || (panfilter == -1)) 
   		return(PARAM_ERROR_RESPONSE); 

   if(crcfilter == -1)tempCrc=false;  //crc filter turn off
   else 
   {
     DecodeFormString(pcValue[crcfilter], pcDecodedString, 32);
     DebugMsg("%s\n", pcDecodedString); 
     
     if(strcmp(pcDecodedString,"on"))
       return(PARAM_ERROR_RESPONSE);
       
     tempCrc=true;                //crc filter turn on
   }
   
   
   // TODO: Decode, parse and apply settings  
   DecodeFormString(pcValue[chn], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if( (pcDecodedString[0]!='c') || (pcDecodedString[1]!='h') )
     return(PARAM_ERROR_RESPONSE);
      
   chn=ustrtoul((char*)&pcDecodedString+2,NULL,10);
   if((chn<0) || (chn>255))
      return(PARAM_ERROR_RESPONSE);
       

   DecodeFormString(pcValue[rxsens], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if(!strcmp(pcDecodedString,"High"))
     tempSens=HIGH;
   else if(!strcmp(pcDecodedString,"Medium"))
     tempSens=MEDIUM;
   else if(!strcmp(pcDecodedString,"Low"))
     tempSens=LOW;
   else if(!strcmp(pcDecodedString,"Lowest"))
     tempSens=LOWEST;
   else return(PARAM_ERROR_RESPONSE);
   
   DecodeFormString(pcValue[panfilter], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if(!strcmp(pcDecodedString,"none"))
     panfilter=0;
   else if((pcDecodedString[0]=='0') && (pcDecodedString[1]=='x'))    
     panfilter=ustrtoul(pcDecodedString,NULL,0);
   else 
     return(PARAM_ERROR_RESPONSE);
     
   
   //------------------------------------------------

   
   DebugMsg("Web Settings: %d, %d, %d, %s \n", chn,tempSens,panfilter,
            ptrSnifferSettings->filterCrc ? "on" : "off");
   
   ptrSnifferSettings->channel=chn;
   ptrSnifferSettings->sensitivity=tempSens;

   unsigned short *tempFilt=(unsigned short*)&ptrSnifferSettings->filterPanId;
   *tempFilt=htons((unsigned short)panfilter);
   
   ptrSnifferSettings->filterCrc=tempCrc;
       
   
   if(Trx_config()==false)
   {
      DebugMsg("Web Config Trx error\n");
      ptrSnifferSettings->state=ERROR;
      return(PARAM_ERROR_RESPONSE);
   } 
   
      
   //       
   //Save setting to Flash memory   
   //       
   if(!Settings_Write(ptrSnifferSettings)) 
     DebugMsg("Save to Flash failed!!\n"); 
   DebugMsg("Setting saved to Flash memory\n");

   return(DEFAULT_CGI_RESPONSE);
}


//******************************************************************************

char *IpsetCGIHandler(int iIndex, int iNumParams, char *pcParam[], char *pcValue[])
{ 
   long ipmode, ipaddr, nmask, gw;
   char pcDecodedString[32];
   struct in_addr temp_ip;
   unsigned long *pucTemp, ulIp, ulMask, ulGw;
    
   ipmode = FindCGIParameter("ipmode", pcParam, iNumParams);
   ipaddr = FindCGIParameter("ipaddr", pcParam, iNumParams);
   nmask = FindCGIParameter("nmask", pcParam, iNumParams);
   gw = FindCGIParameter("gw", pcParam, iNumParams);	 
  
   if((ipmode == -1) || (ipaddr == -1) || (nmask == -1) || (gw == -1)) 
   		return(PARAM_ERROR_RESPONSE); 
    
   // TODO: Decode, parse and apply settings  
   
   DecodeFormString(pcValue[ipmode], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if(!strcmp(pcDecodedString,"dynamic"))
   {
       pucTemp = (unsigned long *)&ptrSnifferSettings->ipaddr;     
      *pucTemp=0;
      
      pucTemp = (unsigned long *)&ptrSnifferSettings->nmask;      
      *pucTemp=0;
      
      pucTemp = (unsigned long *)&ptrSnifferSettings->gw;         
      *pucTemp=0;
       
  
       ptrSnifferSettings->dhcpOn=true;
          
   
   }
   else if(!strcmp(pcDecodedString,"static"))
   {
     
     
     DecodeFormString(pcValue[ipaddr], pcDecodedString, 32);
     DebugMsg("%s\n", pcDecodedString); 
     
     if(!inet_aton(pcDecodedString,&temp_ip))
       return(PARAM_ERROR_RESPONSE);      
     ulIp=(unsigned long)temp_ip.s_addr;      
     
     DecodeFormString(pcValue[nmask], pcDecodedString, 32);
     DebugMsg("%s\n", pcDecodedString);
     
     if(!inet_aton(pcDecodedString,&temp_ip))
       return(PARAM_ERROR_RESPONSE);
     ulMask=(unsigned long)temp_ip.s_addr;
     
     DecodeFormString(pcValue[gw], pcDecodedString, 32);
     DebugMsg("%s\n", pcDecodedString);
     
     if(!inet_aton(pcDecodedString,&temp_ip))
       return(PARAM_ERROR_RESPONSE);
     ulGw=(unsigned long)temp_ip.s_addr;  
     
     //
     // IP addresses can not be zeros in static configure
     //
     if(!ulIp || !ulMask || !ulGw) 
       return(PARAM_ERROR_RESPONSE);   
     
     //
     // IP addresses can not be match together
     //
     if(ulIp==ulMask || ulMask==ulGw || ulIp==ulGw)
       return(PARAM_ERROR_RESPONSE);
     
     //
     // IP address of device must be in same (sub)network like Gateway
     //
     if( (ulIp & ulMask) != (ulGw & ulMask) ) 
       return(PARAM_ERROR_RESPONSE);
     
     //
     // If IP address of device is equal with Remote IP, 
     // than Remote IP is set as Gateway
     //
     pucTemp = (unsigned long *)&ptrSnifferSettings->reipaddr;                               
     if(ulIp==*pucTemp) 
       *pucTemp=ulGw;

     
    //
    // Save settings
    //      
    pucTemp = (unsigned long *)&ptrSnifferSettings->ipaddr; 
    *pucTemp=ulIp;
    
    pucTemp = (unsigned long *)&ptrSnifferSettings->nmask; 
    *pucTemp=ulMask;
    
    pucTemp = (unsigned long *)&ptrSnifferSettings->gw;   
    *pucTemp=ulGw;
    
    ptrSnifferSettings->dhcpOn=false;     
   
   }
   else return(PARAM_ERROR_RESPONSE);
       
   
   //       
   //Save setting to Flash memory   
   //       
   if(!Settings_Write(ptrSnifferSettings)) 
     DebugMsg("Save to Flash failed!!\n"); 
   DebugMsg("Setting saved to Flash memory\n");
   
   
   return(REDIR_CGI_RESPONSE);
}

//******************************************************************************

char *RemoteIpsetCGIHandler(int iIndex, int iNumParams, char *pcParam[],char *pcValue[])
{
   long remoteip, remoteport;
   char pcDecodedString[32];
   struct in_addr temp_ip;
   unsigned long *pucTemp;
   	
   remoteip = FindCGIParameter("remoteip", pcParam, iNumParams);
   remoteport = FindCGIParameter("remoteport", pcParam, iNumParams);	

   if((remoteip == -1) || (remoteport == -1)) 
   		return(PARAM_ERROR_RESPONSE); 

   DecodeFormString(pcValue[remoteip], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if(!inet_aton(pcDecodedString,&temp_ip))
       return(PARAM_ERROR_RESPONSE);
   remoteip=(unsigned long)temp_ip.s_addr;
   DebugMsg("Decode:%u\n", remoteip);

   DecodeFormString(pcValue[remoteport], pcDecodedString, 32);
   DebugMsg("%s\n", pcDecodedString);
   
   if((remoteport=ustrtoul(pcDecodedString,NULL,10))==0)
     return(PARAM_ERROR_RESPONSE);
   DebugMsg("Decode:%u\n", remoteport);
   
   pucTemp = (unsigned long *)&ptrSnifferSettings->ipaddr;
   
   if(remoteip==*pucTemp)  //při rovnosti adresy zařízení a vzdálené adresy
       return(PARAM_ERROR_RESPONSE);
   
   
   //
   //  Save parameters to global variables and apply.
   //
    pucTemp = (unsigned long *)&ptrSnifferSettings->reipaddr;
     
    *pucTemp=(unsigned long)remoteip;
    
    ptrSnifferSettings->report=remoteport;
    
         
    //   
    //Save setting to Flash memory 
    //                 
    if(!Settings_Write(ptrSnifferSettings))   
      DebugMsg("Save to Flash failed!!\n");  
    DebugMsg("Setting saved to Flash memory\n");

   return(DEFAULT_CGI_RESPONSE);	
}
