//*****************************************************************************
// Copyright (C) 2014 Texas Instruments Incorporated
//
// All rights reserved. Property of Texas Instruments Incorporated.
// Restricted rights to use, duplicate or disclose this code are
// granted through contract.
// The program may not be used without the written permission of
// Texas Instruments Incorporated or against the terms and conditions
// stipulated in the agreement under which this program has been supplied,
// and under no circumstances can it be used with non-TI connectivity device.
//
//*****************************************************************************


//*****************************************************************************
//
// Application Name     - HTTP Client Demo
// Application Overview - This sample application demonstrates how to use
//                          HTTP Client (In Minimum mode) API for HTTP based
//                          application development.
//                          This application explain user to how to:
//                          1. Connect to an access point
//                          2. Connect to a HTTP Server with and without proxy
//                          3. Do POST, GET, PUT and DELETE
//                          4. Parse JSON data using “Jasmine JSON Parser”
// Note: To use HTTP Client in minimum mode, user need to compile library (webclient)
// 			with HTTPCli_LIBTYPE_MIN option.
//
// 			HTTP Client (minimal) library supports synchronous mode, redirection
// 			handling, chunked transfer encoding support, proxy support and TLS
// 			support (for SimpleLink Only. TLS on other platforms are disabled)
//
// 			HTTP Client (Full) library supports all the features of the minimal
// 			library + asynchronous mode and content handling support +
// 			TLS support (all platforms). To use HTTP Client in full mode user need
//			to compile library (webclient) with HTTPCli_LIBTYPE_MIN option. For full
//			mode RTOS is needed.
//
// Application Details  -
// http://processors.wiki.ti.com/index.php/
// or
// docs\examples\
//
//*****************************************************************************


#include <string.h>
#include <stddef.h>

// SimpleLink includes
#include "simplelink.h"
#include "simplelinklibrary.h"

// driverlib includes
#include "hw_ints.h"
#include "hw_types.h"
#include "rom.h"
#include "rom_map.h"
#include "prcm.h"
#include "utils.h"
#include "interrupt.h"
#include "timer.h"
// #include "hw_memmap.h"

// free-rtos/TI-rtos include
#include "osi.h"

// common interface includes
#include "timer_if.h"
#include "gpio_if.h"
#include "button_if.h"
#include "uart_if.h"
#include "common.h"
#include "pinmux.h"

// HTTP Client lib
#include <http/client/httpcli.h>
#include <http/client/ssock.h>
#include <http/client/common.h>

// JSON Parser
#include "jsmn.h"

//****************************************************************************
//                          LOCAL DEFINES
//****************************************************************************
#define OSI_STACK_SIZE                   (2048)
#define TASK_PRIORITY                    (1)

//*****************************************************************************
//                         APPLICATION DEFINES
//*****************************************************************************

#define APPLICATION_VERSION "1.0.0"
#define APP_NAME            "Telstra SMS Door Bell"

//*****************************************************************************
//                            HTTP DEFINES
//*****************************************************************************
#define POST_REQUEST_URI 	"/1bshqxx1"
#define POST_DATA           "{\"to\":\"0414000000\", \"body\":\"Knock, knock!\"}"

#define GET_REQUEST_URI 	"/1bshqxx1"

#define APP_KEY 			"yourapikey"
#define APP_SECRET			"yourapisecret"

#define HOST_NAME       	"requestbin.herokuapp.com"
#define HOST_PORT           443

#define PROXY_IP       	    <proxy_ip>
#define PROXY_PORT          <proxy_port>

#define READ_SIZE           1450
#define MAX_BUFF_SIZE       1460

//*****************************************************************************
//                       SNTP CONFIGURATION DEFINES
//*****************************************************************************

#define TIME2013                3565987200u      /* 113 years + 28 days(leap) */
#define YEAR2013                2013
#define SEC_IN_MIN              60
#define SEC_IN_HOUR             3600
#define SEC_IN_DAY              86400

#define SERVER_RESPONSE_TIMEOUT 10
#define GMT_DIFF_TIME_HRS       10
#define GMT_DIFF_TIME_MINS      0

//*****************************************************************************
//               Application specific status/error codes
//*****************************************************************************
typedef enum{
 /* Choosing this number to avoid overlap with host-driver's error codes */
    DEVICE_NOT_IN_STATION_MODE = -0x7D0,       
    DEVICE_START_FAILED = DEVICE_NOT_IN_STATION_MODE - 1,
    INVALID_HEX_STRING = DEVICE_START_FAILED - 1,
    TCP_RECV_ERROR = INVALID_HEX_STRING - 1,
    TCP_SEND_ERROR = TCP_RECV_ERROR - 1,
    FILE_NOT_FOUND_ERROR = TCP_SEND_ERROR - 1,
    INVALID_SERVER_RESPONSE = FILE_NOT_FOUND_ERROR - 1,
    FORMAT_NOT_SUPPORTED = INVALID_SERVER_RESPONSE - 1,
    FILE_OPEN_FAILED = FORMAT_NOT_SUPPORTED - 1,
    FILE_WRITE_ERROR = FILE_OPEN_FAILED - 1,
    INVALID_FILE = FILE_WRITE_ERROR - 1,
    SERVER_CONNECTION_FAILED = INVALID_FILE - 1,
    GET_HOST_IP_FAILED = SERVER_CONNECTION_FAILED  - 1,
    
    STATUS_CODE_MAX = -0xBB8
}e_AppStatusCodes;

//*****************************************************************************
//                 GLOBAL VARIABLES -- Start
//*****************************************************************************
volatile unsigned long  g_ulStatus = 0;//SimpleLink Status
unsigned long  g_ulDestinationIP; // IP address of destination server
unsigned long  g_ulGatewayIP = 0; //Network Gateway IP address
unsigned char  g_ucConnectionSSID[SSID_LEN_MAX+1]; //Connection SSID
unsigned char  g_ucConnectionBSSID[BSSID_LEN_MAX]; //Connection BSSID
unsigned char g_buff[MAX_BUFF_SIZE+1];
long bytesReceived = 0; // variable to store the file size
int g_iSockID;
unsigned long g_ulElapsedSec;
short g_isGeneralVar;
unsigned long g_ulGeneralVar;
unsigned long g_ulGeneralVar1;
char g_acTimeStore[30];
char *g_pcCCPtr;
unsigned short g_uisCCLen;

SlSockAddr_t sAddr;
SlSockAddrIn_t sLocalAddr;

const char g_acSNTPserver[25] = "tic.ntp.telstra.net"; // Telstra SNTP Server

// Queue Structure
typedef struct
{
    //Queue_Elem _elem;
    P_OSI_SPAWN_ENTRY pEntry;
    void* pValue;
}tPushButtonMsg;

static unsigned char accessToken[28] = "yhhjYPLhk69HHYK5ubFL";
static unsigned char expiresIn[8];


//struct
//{
//    unsigned long ulDestinationIP;
//    int iSockID;
//    unsigned long ulElapsedSec;
//    short isGeneralVar;
//    unsigned long ulGeneralVar;
//    unsigned long ulGeneralVar1;
//    char acTimeStore[30];
//    char *pcCCPtr;
//    unsigned short uisCCLen;
//}g_sAppData;

//*****************************************************************************
//                  Globals for Date and Time
//*****************************************************************************
SlDateTime_t dateTime =  {0};

// Tuesday is the 1st day in 2013 - the relative year
const char g_acDaysOfWeek2013[7][3] = {{"Tue"},{"Wed"},{"Thu"},{"Fri"},{"Sat"},{"Sun"},{"Mon"}};
const char g_acMonthOfYear[12][3] = {{"Jan"},{"Feb"},{"Mar"},{"Apr"},{"May"},{"Jun"},{"Jul"},{"Aug"},{"Sep"},{"Oct"},{"Nov"},{"Dec"}};
const char g_acNumOfDaysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const char g_acDigits[] = "0123456789";

//*****************************************************************************
// Globals for time difference calculations
//*****************************************************************************
int hourSet = 25; // Ensures the timeDifference calc will end up in a minus, so will enter the function on first pass or SNTP error
int timeDifference = 0;

//*****************************************************************************
// Globals for buttons
//*****************************************************************************
OsiMsgQ_t g_PBQueue;
OsiTaskHandle g_PushButtonTask;
unsigned int g_uiPBCount = 0;


#if defined(ccs) || defined(gcc)
extern void (* const g_pfnVectors[])(void);
#endif
#if defined(ewarm)
extern uVectorEntry __vector_table;
#endif
//*****************************************************************************
//                 GLOBAL VARIABLES -- End
//*****************************************************************************

//*****************************************************************************
// Forward declarations
//*****************************************************************************
static int HTTPGetMethod(HTTPCli_Handle httpClient);
static int HTTPPostMethod(HTTPCli_Handle httpClient);
static int ConnectToHTTPServer(HTTPCli_Handle httpClient);

//*****************************************************************************
//                         UTILITIES
//*****************************************************************************

//*****************************************************************************
//
//! itoa
//!
//!    @brief  Convert integer to ASCII in decimal base
//!
//!     @param  cNum is input integer number to convert
//!     @param  cString is output string
//!
//!     @return number of ASCII parameters
//!
//!
//
//*****************************************************************************
unsigned short itoa(short cNum, char *cString)
{
    char* ptr;
    short uTemp = cNum;
    unsigned short length;

    // value 0 is a special case
    if (cNum == 0)
    {
        length = 1;
        *cString = '0';

        return length;
    }

    // Find out the length of the number, in decimal base
    length = 0;
    while (uTemp > 0)
    {
        uTemp /= 10;
        length++;
    }

    // Do the actual formatting, right to left
    uTemp = cNum;
    ptr = cString + length;
    while (uTemp > 0)
    {
        --ptr;
        *ptr = g_acDigits[uTemp % 10];
        uTemp /= 10;
    }

    return length;
}

//*****************************************************************************
//
//! getHostIP
//!
//! \brief  This function obtains the server IP address using a DNS lookup
//!
//! \param[in]  pcHostName        The server hostname
//! \param[out] pDestinationIP    This parameter is filled with host IP address.
//!
//! \return On success, +ve value is returned. On error, -ve value is returned
//!
//
//*****************************************************************************
long getHostIP(char* pcHostName, unsigned long * pDestinationIP)
{
    long lStatus = 0;

    lStatus = sl_NetAppDnsGetHostByName((signed char *) pcHostName,
                                            strlen(pcHostName),
                                            pDestinationIP, SL_AF_INET);
//    ASSERT_ON_ERROR(lStatus);
//
    UART_PRINT("\nGet Host IP succeeded.\n\rHost: %s IP: %d.%d.%d.%d \n\r",
                    pcHostName, SL_IPV4_BYTE(*pDestinationIP,3),
                    SL_IPV4_BYTE(*pDestinationIP,2),
                    SL_IPV4_BYTE(*pDestinationIP,1),
                    SL_IPV4_BYTE(*pDestinationIP,0));

    return lStatus;
}

//*****************************************************************************
// SimpleLink Asynchronous Event Handlers -- Start
//*****************************************************************************


//*****************************************************************************
//
//! \brief The Function Handles WLAN Events
//!
//! \param[in]  pWlanEvent - Pointer to WLAN Event Info
//!
//! \return None
//!
//*****************************************************************************
void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent)
{
    switch(pWlanEvent->Event)
    {
        case SL_WLAN_CONNECT_EVENT:
        {
            SET_STATUS_BIT(g_ulStatus, STATUS_BIT_CONNECTION);

            //
            // Information about the connected AP (like name, MAC etc) will be
            // available in 'slWlanConnectAsyncResponse_t'-Applications
            // can use it if required
            //
            //  slWlanConnectAsyncResponse_t *pEventData = NULL;
            // pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
            //

            // Copy new connection SSID and BSSID to global parameters
            memcpy(g_ucConnectionSSID,pWlanEvent->EventData.
                   STAandP2PModeWlanConnected.ssid_name,
                   pWlanEvent->EventData.STAandP2PModeWlanConnected.ssid_len);
            memcpy(g_ucConnectionBSSID,
                   pWlanEvent->EventData.STAandP2PModeWlanConnected.bssid,
                   SL_BSSID_LENGTH);

            UART_PRINT("[WLAN EVENT] STA Connected to the AP: %s ,"
                            " BSSID: %x:%x:%x:%x:%x:%x\n\r",
                      g_ucConnectionSSID,g_ucConnectionBSSID[0],
                      g_ucConnectionBSSID[1],g_ucConnectionBSSID[2],
                      g_ucConnectionBSSID[3],g_ucConnectionBSSID[4],
                      g_ucConnectionBSSID[5]);
        }
        break;

        case SL_WLAN_DISCONNECT_EVENT:
        {
            slWlanConnectAsyncResponse_t*  pEventData = NULL;

            CLR_STATUS_BIT(g_ulStatus, STATUS_BIT_CONNECTION);
            CLR_STATUS_BIT(g_ulStatus, STATUS_BIT_IP_AQUIRED);

            pEventData = &pWlanEvent->EventData.STAandP2PModeDisconnected;

            // If the user has initiated 'Disconnect' request,
            //'reason_code' is SL_USER_INITIATED_DISCONNECTION
            if(SL_USER_INITIATED_DISCONNECTION == pEventData->reason_code)
            {
                UART_PRINT("[WLAN EVENT]Device disconnected from the AP: %s,"
                "BSSID: %x:%x:%x:%x:%x:%x on application's request \n\r",
                           g_ucConnectionSSID,g_ucConnectionBSSID[0],
                           g_ucConnectionBSSID[1],g_ucConnectionBSSID[2],
                           g_ucConnectionBSSID[3],g_ucConnectionBSSID[4],
                           g_ucConnectionBSSID[5]);
            }
            else
            {
                UART_PRINT("[WLAN ERROR]Device disconnected from the AP AP: %s,"
                "BSSID: %x:%x:%x:%x:%x:%x on an ERROR..!! \n\r",
                           g_ucConnectionSSID,g_ucConnectionBSSID[0],
                           g_ucConnectionBSSID[1],g_ucConnectionBSSID[2],
                           g_ucConnectionBSSID[3],g_ucConnectionBSSID[4],
                           g_ucConnectionBSSID[5]);
            }
            memset(g_ucConnectionSSID,0,sizeof(g_ucConnectionSSID));
            memset(g_ucConnectionBSSID,0,sizeof(g_ucConnectionBSSID));
        }
        break;

        default:
        {
            UART_PRINT("[WLAN EVENT] Unexpected event [0x%x]\n\r",
                       pWlanEvent->Event);
        }
        break;
    }
}

//*****************************************************************************
//
//! \brief This function handles network events such as IP acquisition, IP
//!           leased, IP released etc.
//!
//! \param[in]  pNetAppEvent - Pointer to NetApp Event Info
//!
//! \return None
//!
//*****************************************************************************
void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent)
{
    switch(pNetAppEvent->Event)
    {
        case SL_NETAPP_IPV4_IPACQUIRED_EVENT:
        {
            SlIpV4AcquiredAsync_t *pEventData = NULL;

            SET_STATUS_BIT(g_ulStatus, STATUS_BIT_IP_AQUIRED);

            //Ip Acquired Event Data
            pEventData = &pNetAppEvent->EventData.ipAcquiredV4;

            //Gateway IP address
            g_ulGatewayIP = pEventData->gateway;

            UART_PRINT("[NETAPP EVENT] IP Acquired: IP=%d.%d.%d.%d , "
            "Gateway=%d.%d.%d.%d\n\r",
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.ip,3),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.ip,2),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.ip,1),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.ip,0),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.gateway,3),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.gateway,2),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.gateway,1),
            SL_IPV4_BYTE(pNetAppEvent->EventData.ipAcquiredV4.gateway,0));
        }
        break;

        default:
        {
            UART_PRINT("[NETAPP EVENT] Unexpected event [0x%x] \n\r",
                       pNetAppEvent->Event);
        }
        break;
    }
}


//*****************************************************************************
//
//! \brief This function handles HTTP server events
//!
//! \param[in]  pServerEvent - Contains the relevant event information
//! \param[in]    pServerResponse - Should be filled by the user with the
//!                                      relevant response information
//!
//! \return None
//!
//****************************************************************************
void SimpleLinkHttpServerCallback(SlHttpServerEvent_t *pHttpEvent,
                                  SlHttpServerResponse_t *pHttpResponse)
{
    // Unused in this application
}

//*****************************************************************************
//
//! \brief This function handles General Events
//!
//! \param[in]     pDevEvent - Pointer to General Event Info
//!
//! \return None
//!
//*****************************************************************************
void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent)
{
    //
    // Most of the general errors are not FATAL are are to be handled
    // appropriately by the application
    //
    UART_PRINT("[GENERAL EVENT] - ID=[%d] Sender=[%d]\n\r",
               pDevEvent->EventData.deviceEvent.status,
               pDevEvent->EventData.deviceEvent.sender);
}


//*****************************************************************************
//
//! This function handles socket events indication
//!
//! \param[in]      pSock - Pointer to Socket Event Info
//!
//! \return None
//!
//*****************************************************************************
void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
{
    //
    // This application doesn't work w/ socket - Events are not expected
    //
       switch( pSock->Event )
    {
        case SL_SOCKET_TX_FAILED_EVENT:
        	switch( pSock->socketAsyncEvent.SockTxFailData.status )
            {
                case SL_ECLOSE:
                    UART_PRINT("[SOCK ERROR] - close socket (%d) operation "
                    "failed to transmit all queued packets\n\r",
                           pSock->socketAsyncEvent.SockAsyncData.sd);
                    break;
                default:
                    UART_PRINT("[SOCK ERROR] - TX FAILED : socket %d , reason"
                        "(%d) \n\r",
                        pSock->socketAsyncEvent.SockAsyncData.sd,
                        pSock->socketAsyncEvent.SockTxFailData.status);
            }
            break;

        default:
            UART_PRINT("[SOCK EVENT] - Unexpected Event [%x0x]\n\r",pSock->Event);
    }
}


//*****************************************************************************
// SimpleLink Asynchronous Event Handlers -- End
//*****************************************************************************

//*****************************************************************************
//
//! Gets the current time from the selected SNTP server
//!
//! \brief  This function obtains the NTP time from the server.
//!
//! \param  GmtDiffHr is the GMT Time Zone difference in hours
//! \param  GmtDiffMins is the GMT Time Zone difference in minutes
//!
//! \return 0 : success, -ve : failure
//!
//*****************************************************************************
long GetSNTPTime(unsigned char ucGmtDiffHr, unsigned char ucGmtDiffMins)
{

/*
                            NTP Packet Header:

       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9  0  1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |LI | VN  |Mode |    Stratum    |     Poll      |   Precision    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          Root  Delay                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                       Root  Dispersion                         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                     Reference Identifier                       |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                                |
      |                    Reference Timestamp (64)                    |
      |                                                                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                                |
      |                    Originate Timestamp (64)                    |
      |                                                                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                                |
      |                     Receive Timestamp (64)                     |
      |                                                                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                                |
      |                     Transmit Timestamp (64)                    |
      |                                                                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                 Key Identifier (optional) (32)                 |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                                                                |
      |                                                                |
      |                 Message Digest (optional) (128)                |
      |                                                                |
      |                                                                |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

*/
    char cDataBuf[48];
    long lRetVal = 0;
    int iAddrSize;

    // Send a query to the NTP server to get the NTP time
    memset(cDataBuf, 0, sizeof(cDataBuf));
    cDataBuf[0] = '\x1b';

    sAddr.sa_family = AF_INET;
    // the source port
    sAddr.sa_data[0] = 0x00;
    sAddr.sa_data[1] = 0x7B;    // UDP port number for NTP is 123
    sAddr.sa_data[2] = (char)((g_ulDestinationIP>>24)&0xff);
    sAddr.sa_data[3] = (char)((g_ulDestinationIP>>16)&0xff);
    sAddr.sa_data[4] = (char)((g_ulDestinationIP>>8)&0xff);
    sAddr.sa_data[5] = (char)(g_ulDestinationIP&0xff);

    lRetVal = sl_SendTo(g_iSockID, cDataBuf, sizeof(cDataBuf), 0, &sAddr, sizeof(sAddr));
    if (lRetVal != sizeof(cDataBuf))
    {
    	UART_PRINT("Could not send request to SNTP server: %i\n\r",lRetVal);
        return lRetVal;
    }

    // Wait to receive the NTP time from the server
    sLocalAddr.sin_family = SL_AF_INET;
    sLocalAddr.sin_port = 0;
    sLocalAddr.sin_addr.s_addr = 0;
    if(g_ulElapsedSec == 0)
    {
        lRetVal = sl_Bind(g_iSockID, (SlSockAddr_t *)&sLocalAddr, sizeof(SlSockAddrIn_t));
        if(lRetVal < 0)
        {
        	UART_PRINT("Could not bind to SNTP server: %i\n\r",lRetVal);
            return lRetVal;
        }
    }

    iAddrSize = sizeof(SlSockAddrIn_t);

    lRetVal = sl_RecvFrom(g_iSockID, cDataBuf, sizeof(cDataBuf), 0, (SlSockAddr_t *)&sLocalAddr, (SlSocklen_t*)&iAddrSize);
    if(lRetVal < 0)
    {
    	UART_PRINT("Did not receive valid response from SNTP server: %i\n\r",lRetVal);
        return lRetVal;
    }

    // Confirm that the MODE is 4 --> server
    if ((cDataBuf[0] & 0x7) != 4)    // expect only server response
    {
        //ASSERT_ON_ERROR(SERVER_GET_TIME_FAILED);  // MODE is not server, abort
    	return -1;
    }
    else
    {
        unsigned char iIndex;

        // Getting the data from the Transmit Timestamp (seconds) field
        // This is the time at which the reply departed the
        // server for the client
        g_ulElapsedSec = cDataBuf[40];
        g_ulElapsedSec <<= 8;
        g_ulElapsedSec += cDataBuf[41];
        g_ulElapsedSec <<= 8;
        g_ulElapsedSec += cDataBuf[42];
        g_ulElapsedSec <<= 8;
        g_ulElapsedSec += cDataBuf[43];

        // seconds are relative to 0h on 1 January 1900
        g_ulElapsedSec -= TIME2013;

        // in order to correct the timezone
        g_ulElapsedSec += (ucGmtDiffHr * SEC_IN_HOUR);
        g_ulElapsedSec += (ucGmtDiffMins * SEC_IN_MIN);

        g_pcCCPtr = &g_acTimeStore[0];

        // day, number of days since beginning of 2013
        g_isGeneralVar = g_ulElapsedSec/SEC_IN_DAY;
        memcpy(g_pcCCPtr, g_acDaysOfWeek2013[g_isGeneralVar%7], 3);
        g_pcCCPtr += 3;
        *g_pcCCPtr++ = '\x20';

        // month
        g_isGeneralVar %= 365;
        for (iIndex = 0; iIndex < 12; iIndex++)
        {
            g_isGeneralVar -= g_acNumOfDaysPerMonth[iIndex];
            if (g_isGeneralVar < 0)
                    break;
        }
        if(iIndex == 12)
        {
            iIndex = 0;
        }
        memcpy(g_pcCCPtr, g_acMonthOfYear[iIndex], 3);
        g_pcCCPtr += 3;
        *g_pcCCPtr++ = '\x20';

        // Set the Month Value
        dateTime.sl_tm_mon = iIndex + 1;

        // date
        // restore the day in current month
        g_isGeneralVar += g_acNumOfDaysPerMonth[iIndex];
        g_uisCCLen = itoa(g_isGeneralVar + 1, g_pcCCPtr);
        g_pcCCPtr += g_uisCCLen;
        *g_pcCCPtr++ = '\x20';

        // Set the Date
        dateTime.sl_tm_day = g_isGeneralVar + 1;

        // time
        g_ulGeneralVar = g_ulElapsedSec%SEC_IN_DAY;

        // number of seconds per hour
        g_ulGeneralVar1 = g_ulGeneralVar%SEC_IN_HOUR;

        // number of hours
        g_ulGeneralVar /= SEC_IN_HOUR;
        g_uisCCLen = itoa(g_ulGeneralVar, g_pcCCPtr);
        g_pcCCPtr += g_uisCCLen;
        *g_pcCCPtr++ = ':';

        // Set the hour
        dateTime.sl_tm_hour = g_ulGeneralVar;

        // number of minutes per hour
        g_ulGeneralVar = g_ulGeneralVar1/SEC_IN_MIN;

        // Set the minutes
        dateTime.sl_tm_min = g_ulGeneralVar;

        // number of seconds per minute
        g_ulGeneralVar1 %= SEC_IN_MIN;
        g_uisCCLen = itoa(g_ulGeneralVar, g_pcCCPtr);
        g_pcCCPtr += g_uisCCLen;
        *g_pcCCPtr++ = ':';
        g_uisCCLen = itoa(g_ulGeneralVar1, g_pcCCPtr);
        g_pcCCPtr += g_uisCCLen;
        *g_pcCCPtr++ = '\x20';

        //Set the seconds
        dateTime.sl_tm_sec = g_ulGeneralVar1;

        // year
        // number of days since beginning of 2013
        g_ulGeneralVar = g_ulElapsedSec/SEC_IN_DAY;
        g_ulGeneralVar /= 365;
        g_uisCCLen = itoa(YEAR2013 + g_ulGeneralVar, g_pcCCPtr);
        g_pcCCPtr += g_uisCCLen;

        *g_pcCCPtr++ = '\0';

        //Set the year
        dateTime.sl_tm_year = 2013 + g_ulGeneralVar;

        UART_PRINT("Response from server: ");
        UART_PRINT((char *)g_acSNTPserver);
        UART_PRINT("\n\r");
        UART_PRINT(g_acTimeStore);
        UART_PRINT("\n\r");

        //Set time of the device for certificate verification.
        lRetVal = setDeviceTimeDate();
        if(lRetVal < 0)
        {
        	UART_PRINT("Unable to set time in the device. Error Number: %i\n\r",lRetVal);
            return lRetVal;
        }
    }

    return SUCCESS;
}

//*****************************************************************************
//
//! This function obtains the current time from a SNTP server if required due
//! to not having current time (when booting up) or periodically to update
//! the time
//!
//! \param None
//!
//! \return  0 on success else error code
//! \return  Error Number of failure
//
//*****************************************************************************
long GetCurrentTime()
{
    int iSocketDesc;
    long lRetVal = -1;

	// Create UDP socket
	iSocketDesc = sl_Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(iSocketDesc < 0)
	{
		UART_PRINT("Could not create UDP socket. Error Number: %i\n\r",iSocketDesc);
		close(iSocketDesc);
		return iSocketDesc;
	}
	g_iSockID = iSocketDesc;

	// Get the NTP server host IP address using the DNS lookup
	lRetVal = getHostIP((char*)g_acSNTPserver, &g_ulDestinationIP);
	if( lRetVal >= 0)
	{
		// Configure the recieve timeout
		struct SlTimeval_t timeVal;
		timeVal.tv_sec =  SERVER_RESPONSE_TIMEOUT;    // Seconds
		timeVal.tv_usec = 0;     // Microseconds. 10000 microseconds resolution
		lRetVal = sl_SetSockOpt(g_iSockID,SL_SOL_SOCKET,SL_SO_RCVTIMEO, (unsigned char*)&timeVal, sizeof(timeVal));
		if(lRetVal < 0)
		{
			UART_PRINT("Could not configure socket option (receive timeout). Error Number: %i\n\r",lRetVal);
			close(iSocketDesc);
			return lRetVal;
		}
	}
	else
	{
		UART_PRINT("DNS lookup failed. Error Number: %i\n\r",lRetVal);
		close(iSocketDesc);
		return lRetVal;
	}

	// Get current time from the SNTP server
	UART_PRINT("Fetching Time From SNTP Server\n\r");
	lRetVal = GetSNTPTime(GMT_DIFF_TIME_HRS, GMT_DIFF_TIME_MINS);
	if(lRetVal < 0)
	{
		UART_PRINT("Server Get Time failed. Error Number: %i\n\r",lRetVal);
		close(iSocketDesc);
		return lRetVal;
	}
	else
	{
		hourSet = dateTime.sl_tm_hour; // Set to current hour as we did get the time successfully
		UART_PRINT("Server Get Time Successful - RTC Updated\n\n\r");
	}

	// Close the socket
	close(iSocketDesc);

	return SUCCESS;
}


//*****************************************************************************
//
//! \brief This function initializes the application variables
//!
//! \param    None
//!
//! \return None
//!
//*****************************************************************************
static void InitializeAppVariables()
{
    g_ulStatus = 0;
    g_ulGatewayIP = 0;
    memset(g_ucConnectionSSID,0,sizeof(g_ucConnectionSSID));
    memset(g_ucConnectionBSSID,0,sizeof(g_ucConnectionBSSID));
}


//*****************************************************************************
//! \brief This function puts the device in its default state. It:
//!           - Set the mode to STATION
//!           - Configures connection policy to Auto and AutoSmartConfig
//!           - Deletes all the stored profiles
//!           - Enables DHCP
//!           - Disables Scan policy
//!           - Sets Tx power to maximum
//!           - Sets power policy to normal
//!           - Unregister mDNS services
//!           - Remove all filters
//!
//! \param   none
//! \return  On success, zero is returned. On error, negative is returned
//*****************************************************************************
static long ConfigureSimpleLinkToDefaultState()
{
    SlVersionFull   ver = {0};
    _WlanRxFilterOperationCommandBuff_t  RxFilterIdMask = {0};

    unsigned char ucVal = 1;
    unsigned char ucConfigOpt = 0;
    unsigned char ucConfigLen = 0;
    unsigned char ucPower = 0;

    long lRetVal = -1;
    long lMode = -1;

    lMode = sl_Start(0, 0, 0);
    ASSERT_ON_ERROR(lMode);

    // If the device is not in station-mode, try configuring it in station-mode 
    if (ROLE_STA != lMode)
    {
        if (ROLE_AP == lMode)
        {
            // If the device is in AP mode, we need to wait for this event 
            // before doing anything 
            while(!IS_IP_ACQUIRED(g_ulStatus))
            {
#ifndef SL_PLATFORM_MULTI_THREADED
              _SlNonOsMainLoopTask(); 
#endif
            }
        }

        // Switch to STA role and restart 
        lRetVal = sl_WlanSetMode(ROLE_STA);
        ASSERT_ON_ERROR(lRetVal);

        lRetVal = sl_Stop(0xFF);
        ASSERT_ON_ERROR(lRetVal);

        lRetVal = sl_Start(0, 0, 0);
        ASSERT_ON_ERROR(lRetVal);

        // Check if the device is in station again 
        if (ROLE_STA != lRetVal)
        {
            // We don't want to proceed if the device is not coming up in STA-mode 
            return DEVICE_NOT_IN_STATION_MODE;
        }
    }
    
    // Get the device's version-information
    ucConfigOpt = SL_DEVICE_GENERAL_VERSION;
    ucConfigLen = sizeof(ver);
    lRetVal = sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &ucConfigOpt, 
                                &ucConfigLen, (unsigned char *)(&ver));
    ASSERT_ON_ERROR(lRetVal);
    
    UART_PRINT("Host Driver Version: %s\n\r",SL_DRIVER_VERSION);
    UART_PRINT("Build Version %d.%d.%d.%d.31.%d.%d.%d.%d.%d.%d.%d.%d\n\r",
    ver.NwpVersion[0],ver.NwpVersion[1],ver.NwpVersion[2],ver.NwpVersion[3],
    ver.ChipFwAndPhyVersion.FwVersion[0],ver.ChipFwAndPhyVersion.FwVersion[1],
    ver.ChipFwAndPhyVersion.FwVersion[2],ver.ChipFwAndPhyVersion.FwVersion[3],
    ver.ChipFwAndPhyVersion.PhyVersion[0],ver.ChipFwAndPhyVersion.PhyVersion[1],
    ver.ChipFwAndPhyVersion.PhyVersion[2],ver.ChipFwAndPhyVersion.PhyVersion[3]);

    // Set connection policy to Auto + SmartConfig 
    //      (Device's default connection policy)
    lRetVal = sl_WlanPolicySet(SL_POLICY_CONNECTION, 
                                SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0);
    ASSERT_ON_ERROR(lRetVal);

    // Remove all profiles
    lRetVal = sl_WlanProfileDel(0xFF);
    ASSERT_ON_ERROR(lRetVal);

    //
    // Device in station-mode. Disconnect previous connection if any
    // The function returns 0 if 'Disconnected done', negative number if already
    // disconnected Wait for 'disconnection' event if 0 is returned, Ignore 
    // other return-codes
    //
    lRetVal = sl_WlanDisconnect();
    if(0 == lRetVal)
    {
        // Wait
        while(IS_CONNECTED(g_ulStatus))
        {
#ifndef SL_PLATFORM_MULTI_THREADED
              _SlNonOsMainLoopTask(); 
#endif
        }
    }

    // Enable DHCP client
    lRetVal = sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE,1,1,&ucVal);
    ASSERT_ON_ERROR(lRetVal);

    // Disable scan
    ucConfigOpt = SL_SCAN_POLICY(0);
    lRetVal = sl_WlanPolicySet(SL_POLICY_SCAN , ucConfigOpt, NULL, 0);
    ASSERT_ON_ERROR(lRetVal);

    // Set Tx power level for station mode
    // Number between 0-15, as dB offset from max power - 0 will set max power
    ucPower = 0;
    lRetVal = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, 
            WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1, (unsigned char *)&ucPower);
    ASSERT_ON_ERROR(lRetVal);

    // Set PM policy to normal
    lRetVal = sl_WlanPolicySet(SL_POLICY_PM , SL_NORMAL_POLICY, NULL, 0);
    ASSERT_ON_ERROR(lRetVal);

    // Unregister mDNS services
    lRetVal = sl_NetAppMDNSUnRegisterService(0, 0);
    ASSERT_ON_ERROR(lRetVal);

    // Remove  all 64 filters (8*8)
    memset(RxFilterIdMask.FilterIdMask, 0xFF, 8);
    lRetVal = sl_WlanRxFilterSet(SL_REMOVE_RX_FILTER, (_u8 *)&RxFilterIdMask,
                       sizeof(_WlanRxFilterOperationCommandBuff_t));
    ASSERT_ON_ERROR(lRetVal);


    lRetVal = sl_Stop(SL_STOP_TIMEOUT);
    ASSERT_ON_ERROR(lRetVal);

    InitializeAppVariables();

    return SUCCESS;
}



//****************************************************************************
//
//! \brief Connecting to a WLAN Accesspoint
//!
//!  This function connects to the required AP (SSID_NAME) with Security
//!  parameters specified in te form of macros at the top of this file
//!
//! \param  Status value
//!
//! \return  None
//!
//! \warning    If the WLAN connection fails or we don't aquire an IP
//!            address, It will be stuck in this function forever.
//
//****************************************************************************
static long WlanConnect()
{
    SlSecParams_t secParams = {0};
    long lRetVal = 0;

    secParams.Key = (signed char *)SECURITY_KEY;
    secParams.KeyLen = strlen(SECURITY_KEY);
    secParams.Type = SECURITY_TYPE;

    lRetVal = sl_WlanConnect((signed char *)SSID_NAME,
                           strlen((const char *)SSID_NAME), 0, &secParams, 0);
    ASSERT_ON_ERROR(lRetVal);

    // Wait for WLAN Event
    while((!IS_CONNECTED(g_ulStatus)) || (!IS_IP_ACQUIRED(g_ulStatus)))
    {
        // wait till connects to an AP
        //_SlNonOsMainLoopTask();

    }

    return SUCCESS;

}


//*****************************************************************************
//
//! \brief Flush response body.
//!
//! \param[in]  httpClient - Pointer to HTTP Client instance
//!
//! \return 0 on success else error code on failure
//!
//*****************************************************************************
static int FlushHTTPResponse(HTTPCli_Handle httpClient)
{
    const char *ids[2] = {
                            HTTPCli_FIELD_NAME_CONNECTION, /* App will get connection header value. all others will skip by lib */
                            NULL
                         };
    char buf[128];
    int id;
    int len = 1;
    bool moreFlag = 0;
    char ** prevRespFilelds = NULL;


    /* Store previosly store array if any */
    prevRespFilelds = HTTPCli_setResponseFields(httpClient, ids);

    /* Read response headers */
    while ((id = HTTPCli_getResponseField(httpClient, buf, sizeof(buf), &moreFlag))
            != HTTPCli_FIELD_ID_END)
    {

        if(id == 0)
        {
            if(!strncmp(buf, "close", sizeof("close")))
            {
                UART_PRINT("Connection terminated by server\n\r");
            }
        }

    }

    /* Restore previosuly store array if any */
    HTTPCli_setResponseFields(httpClient, (const char **)prevRespFilelds);

    while(1)
    {
        /* Read response data/body */
        /* Note:
                moreFlag will be set to 1 by HTTPCli_readResponseBody() call, if more
                data is available Or in other words content length > length of buffer.
                The remaining data will be read in subsequent call to HTTPCli_readResponseBody().
                Please refer HTTP Client Libary API documenation @ref HTTPCli_readResponseBody
                for more information.
        */
        HTTPCli_readResponseBody(httpClient, buf, sizeof(buf) - 1, &moreFlag);
        ASSERT_ON_ERROR(len);

        if ((len - 2) >= 0 && buf[len - 2] == '\r' && buf [len - 1] == '\n'){
            break;
        }

        if(!moreFlag)
        {
            /* There no more data. break the loop. */
            break;
        }
    }
    return 0;
}


//*****************************************************************************
//
//! \brief Handler for parsing JSON data
//!
//! \param[in]  ptr - Pointer to http response body data
//!
//! \return 0 on success else error code on failure
//!
//*****************************************************************************
int ParseJSONData(char *ptr)
{
	int i;
	long lRetVal = 0;
    int noOfToken;
    jsmn_parser parser;
    jsmntok_t   *tokenList;
	unsigned char keyString[200];
//	unsigned char keyStringValue[200];


    /* Initialize JSON PArser */
    jsmn_init(&parser);

    /* Get number of JSON token in stream as we we dont know how many tokens need to pass */
    noOfToken = jsmn_parse(&parser, (const char *)ptr, strlen((const char *)ptr), NULL, 10);
    if(noOfToken <= 0)
    {
    	UART_PRINT("Failed to initialize JSON parser\n\r");
    	return -1;

    }

    /* Allocate memory to store token */
    tokenList = (jsmntok_t *) malloc(noOfToken*sizeof(jsmntok_t));
    if(tokenList == NULL)
    {
        UART_PRINT("Failed to allocate memory\n\r");
        return -1;
    }

    /* Initialize JSON Parser again */
    jsmn_init(&parser);
    noOfToken = jsmn_parse(&parser, (const char *)ptr, strlen((const char *)ptr), tokenList, noOfToken);
    if(noOfToken < 0)
    {
    	UART_PRINT("Failed to parse JSON tokens\n\r");
    	lRetVal = noOfToken;
    }
    else
    {
    	UART_PRINT("Successfully parsed %ld JSON tokens\n\r", noOfToken);
    }

    /* Iterate and extract tokens */
	for (i = 1; tokenList[i].end != 0 && tokenList[i].end < tokenList[0].end; i++)
	{
		jsmntok_t key = tokenList[i];
		jsmntok_t keyValue = tokenList[i+1];

		unsigned int length = key.end - key.start;
		unsigned int lengthValue = keyValue.end - keyValue.start;

		memcpy(keyString, &ptr[key.start], length);
		keyString[length] = '\0';

//		memcpy(keyStringValue, &ptr[keyValue.start], lengthValue);
//		keyStringValue[lengthValue] = '\0';

		UART_PRINT("%i\n\r", i);
		UART_PRINT("Key: %s\n\r", keyString);
		UART_PRINT("tokens[0].end: %i\n\r", tokenList[0].end);
		UART_PRINT("tokens[%i].end: %i\n\r",i, tokenList[i].end);


		if (tokenList[i].type == JSMN_STRING || tokenList[i].type == JSMN_PRIMITIVE)
		{
			if (strcmp((const char *)keyString, "access_token") == 0)
			{
				memcpy(accessToken, &ptr[keyValue.start], lengthValue);
				accessToken[lengthValue] = '\0';
			}

			if (strcmp((const char *)keyString, "expires_in") == 0)
			{
				memcpy(expiresIn, &ptr[keyValue.start], lengthValue);
				expiresIn[lengthValue] = '\0';
			}
			UART_PRINT("%.*s\n\r", tokenList[i].end - tokenList[i].start, ptr + tokenList[i].start);
		}
		else if (tokenList[i].type == JSMN_ARRAY)
		{
//			UART_PRINT("[%d elems]\n", tokenList[i].size);
		}
		else if (tokenList[i].type == JSMN_OBJECT)
		{
//			UART_PRINT("{%d elems}\n", tokenList[i].size);
		}
		else
		{
			//UART_PRINT(tokens[i]);
		}

	}

	free(tokenList);

    return lRetVal;
}

/*!
    \brief This function read respose from server and dump on console

    \param[in]      httpClient - HTTP Client object

    \return         0 on success else -ve

    \note

    \warning
*/
static int readResponse(HTTPCli_Handle httpClient)
{
	long lRetVal = 0;
	int bytesRead = 0;
	int id = 0;
	unsigned long len = 0;
	int json = 0;
	char *dataBuffer=NULL;
	bool moreFlags = 1;
	const char *ids[4] = {
	                        HTTPCli_FIELD_NAME_CONTENT_LENGTH,
			                HTTPCli_FIELD_NAME_CONNECTION,
			                HTTPCli_FIELD_NAME_CONTENT_TYPE,
			                NULL
	                     };

	/* Read HTTP POST request status code */
	lRetVal = HTTPCli_getResponseStatus(httpClient);
	if(lRetVal > 0)
	{
		switch(lRetVal)
		{
		case 200:
		{
			UART_PRINT("HTTP Status 200\n\r");
			/*
                 Set response header fields to filter response headers. All
                  other than set by this call we be skipped by library.
			 */
			HTTPCli_setResponseFields(httpClient, (const char **)ids);

			/* Read filter response header and take appropriate action. */
			/* Note:
                    1. id will be same as index of fileds in filter array setted
                    in previous HTTPCli_setResponseFields() call.

                    2. moreFlags will be set to 1 by HTTPCli_getResponseField(), if  field
                    value could not be completely read. A subsequent call to
                    HTTPCli_getResponseField() will read remaining field value and will
                    return HTTPCli_FIELD_ID_DUMMY. Please refer HTTP Client Libary API
                    documenation @ref HTTPCli_getResponseField for more information.
			 */
			while((id = HTTPCli_getResponseField(httpClient, (char *)g_buff, sizeof(g_buff), &moreFlags))
					!= HTTPCli_FIELD_ID_END)
			{

				switch(id)
				{
				case 0: /* HTTPCli_FIELD_NAME_CONTENT_LENGTH */
				{
					len = strtoul((char *)g_buff, NULL, 0);
				}
				break;
				case 1: /* HTTPCli_FIELD_NAME_CONNECTION */
				{
				}
				break;
				case 2: /* HTTPCli_FIELD_NAME_CONTENT_TYPE */
				{
					if(strncmp((const char *)g_buff, "application/json",
							sizeof("application/json")))
					{
						json = 1;
					}
					else
					{
						/* Note:
                                Developers are advised to use appropriate
                                content handler. In this example all content
                                type other than json are treated as plain text.
						 */
						json = 0;
					}
					UART_PRINT(HTTPCli_FIELD_NAME_CONTENT_TYPE);
					UART_PRINT(" : ");
					UART_PRINT("application/json\n\r");
				}
				break;
				default:
				{
					UART_PRINT("Wrong filter id\n\r");
					lRetVal = -1;
					goto end;
				}
				}
			}
			bytesRead = 0;
			if(len > sizeof(g_buff))
			{
				dataBuffer = (char *) malloc(len);
				if(dataBuffer)
				{
					UART_PRINT("Failed to allocate memory\n\r");
					lRetVal = -1;
					goto end;
				}
			}
			else
			{
				dataBuffer = (char *)g_buff;
			}

			/* Read response data/body */
			/* Note:
                    moreFlag will be set to 1 by HTTPCli_readResponseBody() call, if more
		            data is available Or in other words content length > length of buffer.
		            The remaining data will be read in subsequent call to HTTPCli_readResponseBody().
		            Please refer HTTP Client Libary API documenation @ref HTTPCli_readResponseBody
		            for more information

			 */
			bytesRead = HTTPCli_readResponseBody(httpClient, (char *)dataBuffer, len, &moreFlags);
			if(bytesRead < 0)
			{
				UART_PRINT("Failed to received response body\n\r");
				lRetVal = bytesRead;
				goto end;
			}
			else if( bytesRead < len || moreFlags)
			{
				UART_PRINT("Mismatch in content length and received data length\n\r");
				goto end;
			}
			dataBuffer[bytesRead] = '\0';

			if(json)
			{
				/* Parse JSON data */
				lRetVal = ParseJSONData(dataBuffer);
				if(lRetVal < 0)
				{
					goto end;
				}
			}
			else
			{
				/* treating data as a plain text */
			}

		}
		break;

		case 404:
			UART_PRINT("File not found. \r\n");
			/* Handle response body as per requirement.
                  Note:
                    Developers are advised to take appopriate action for HTTP
                    return status code else flush the response body.
                    In this example we are flushing response body in default
                    case for all other than 200 HTTP Status code.
			 */
		default:
			/* Note:
              Need to flush received buffer explicitly as library will not do
              for next request.Apllication is responsible for reading all the
              data.
			 */
			FlushHTTPResponse(httpClient);
			break;
		}
	}
	else
	{
		UART_PRINT("Failed to receive data from server.\r\n");
		goto end;
	}

	lRetVal = 0;

end:
    if(len > sizeof(g_buff) && (dataBuffer != NULL))
	{
	    free(dataBuffer);
    }
    return lRetVal;
}

//*****************************************************************************
//
//!  \brief     Cleans up
//!
//! \param[in]  httpClient - Pointer to http client
//!
//! \return 0 on success
//*****************************************************************************
static int cleanUp(HTTPCli_Handle httpClient)
{
    HTTPCli_disconnect(httpClient);
    HTTPCli_destruct(httpClient);

    return 0;
}


//*****************************************************************************
//
//!  \brief     Sends SMS
//!
//!  \param    pValue        -    pointer to Input Data
//!
//!  \return void
//!  \note
//!  \warning
//*****************************************************************************
void PushButtonSmsSend(void* pValue)
{

    long lRetVal = -1;
    HTTPCli_Struct httpClient;

    UART_PRINT("\n\r");
    UART_PRINT("******** Button Pressed Start ********\n\r");

//    if(!IS_CONNECTED(Network_IF_CurrentMCUState()))
//    {
//        LedTimerConfigNStart();
//        lRetVal = Network_IF_ConnectAP(SSID_NAME,SecurityParams);
//        if(lRetVal < 0)
//        {
//           UART_PRINT("Error: %d Connecting to an AP.\n\r",lRetVal);
//           return;
//        }
//
//    }

    // Get the current time from an SNTP server
    lRetVal = -1;
    while (lRetVal < 0)
    {
    	lRetVal = GetCurrentTime();
		if(lRetVal < 0)
		{
			UART_PRINT("Failed to get time from SNTP server. Retrying.\n\r");
		}
    }

    // Connect securely to server
    lRetVal = ConnectToHTTPServer(&httpClient);
    if(lRetVal < 0)
    {
    	UART_PRINT("ConnectHTTPServer Failed.\n\r");
    }

    // Get the access token
    lRetVal = HTTPGetMethod(&httpClient);
    if(lRetVal < 0)
    {
    	UART_PRINT("HTTP GET failed.\n\r");
    }

    // Semd SMS
    lRetVal = HTTPPostMethod(&httpClient);
    if(lRetVal < 0)
    {
    	UART_PRINT("HTTP POST failed.\n\r");
    }

    cleanUp(&httpClient);

    //Enable GPIO Interrupt
    Button_IF_EnableInterrupt(SW2);
    //Button_IF_EnableInterrupt(SW3); //If using SW3 button

    UART_PRINT("\n\r");
    UART_PRINT("******** Button Pressed End ********\n\r");

    return;
}

//*****************************************************************************
// Button Event Handlers
//*****************************************************************************

//*****************************************************************************
//!   \brief     Push Button Task to Handle Trigger from Push Button
//!
//!   \param    pvParameters        -    pointer to the task parameter
//!
//!   \return void
//!   \note
//!   \warning
//*****************************************************************************
void PushButtonHandler(void *pvParameters)
{
    tPushButtonMsg Msg;
    int ret=0;

    for(;;)
    {
        ret = osi_MsgQRead( &g_PBQueue, &Msg, OSI_WAIT_FOREVER );
        if(OSI_OK==ret)
        {
            Msg.pEntry(Msg.pValue);
        }
    }
}

//*****************************************************************************
//
//!  \brief     Interrupt Handler to Send SMS upon Press of Push Button (S3 or S2)
//!
//!  \param    none
//!
//!  \return void
//!  \note
//
//*****************************************************************************
void SendSmsInterruptHandler()
{
    tPushButtonMsg sMsg;
    sMsg.pEntry = &PushButtonSmsSend;
    sMsg.pValue = NULL;
    osi_MsgQWrite(&g_PBQueue,&sMsg,OSI_NO_WAIT);
}

//*****************************************************************************
//
//! \brief HTTP POST Demonstration
//!
//! \param[in]  httpClient - Pointer to http client
//!
//! \return 0 on success else error code on failure
//!
//*****************************************************************************
static int HTTPPostMethod(HTTPCli_Handle httpClient)
{
    bool moreFlags = 1;
    bool lastFlag = 1;
    char tmpBuf[4];
    long lRetVal = 0;

    static char bearerToken[36] = "";
   	strcat(bearerToken, "Bearer ");
    strcat(bearerToken, (const char *)accessToken);
    strcat(bearerToken, "\0");

    HTTPCli_Field fields[5] = {
                                {HTTPCli_FIELD_NAME_HOST, HOST_NAME},
								{HTTPCli_FIELD_NAME_ACCEPT, "*/*"},
                                {HTTPCli_FIELD_NAME_CONTENT_TYPE, "application/json"},
                                {"Authorization", (const char *)bearerToken},
                                {NULL, NULL}
                            };


    /* Set request header fields to be sent for HTTP request. */
    HTTPCli_setRequestFields(httpClient, fields);

    /* Send POST method request. */
    /* Here we are setting moreFlags = 1 as there are some more header fields need to send
       other than setted in previous call HTTPCli_setRequestFields() at later stage.
       Please refer HTTP Library API documentaion @ref HTTPCli_sendRequest for more information.
    */
    moreFlags = 1;
    lRetVal = HTTPCli_sendRequest(httpClient, HTTPCli_METHOD_POST, POST_REQUEST_URI, moreFlags);
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to send HTTP POST request header.\n\r");
        return lRetVal;
    }

    sprintf((char *)tmpBuf, "%d", (sizeof(POST_DATA)-1));

    /* Here we are setting lastFlag = 1 as it is last header field.
       Please refer HTTP Library API documentaion @ref HTTPCli_sendField for more information.
    */
    lastFlag = 1;
    lRetVal = HTTPCli_sendField(httpClient, HTTPCli_FIELD_NAME_CONTENT_LENGTH, (const char *)tmpBuf, lastFlag);
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to send HTTP POST request header.\n\r");
        return lRetVal;
    }


    /* Send POST data/body */
    lRetVal = HTTPCli_sendRequestBody(httpClient, POST_DATA, (sizeof(POST_DATA)-1));
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to send HTTP POST request body.\n\r");
        return lRetVal;
    }

    //lRetVal = readResponse(httpClient);

    return lRetVal;
}


//*****************************************************************************
//
//! \brief HTTP GET Demonstration
//!
//! \param[in]  httpClient - Pointer to http client
//!
//! \return 0 on success else error code on failure
//!
//*****************************************************************************
static int HTTPGetMethod(HTTPCli_Handle httpClient)
{
  
    long lRetVal = 0;
    HTTPCli_Field fields[4] = {
                                {HTTPCli_FIELD_NAME_HOST, HOST_NAME},
                                {HTTPCli_FIELD_NAME_ACCEPT, "*/*"},
                                {HTTPCli_FIELD_NAME_CONTENT_LENGTH, "0"},
                                {NULL, NULL}
                            };
    bool        moreFlags;
    
    /* Set request header fields to be send for HTTP request. */
    HTTPCli_setRequestFields(httpClient, fields);

    /* Send GET method request. */
    /* Here we are setting moreFlags = 0 as there are no more header fields need to send
       at later stage. Please refer HTTP Library API documentaion @ HTTPCli_sendRequest
       for more information.
    */
    moreFlags = 0;
    lRetVal = HTTPCli_sendRequest(httpClient, HTTPCli_METHOD_GET, GET_REQUEST_URI, moreFlags);
    if(lRetVal < 0)
    {
        UART_PRINT("Failed to send HTTP GET request.\n\r");
        return lRetVal;
    }

    lRetVal = readResponse(httpClient);

    return lRetVal;
}


//*****************************************************************************
//
//! Function to connect to AP
//!
//! \param  none
//!
//! \return Error-code or SUCCESS
//!
//*****************************************************************************
static long ConnectToAP()
{
    long lRetVal = -1;
    
    //
    // Following function configure the device to default state by cleaning
    // the persistent settings stored in NVMEM (viz. connection profiles &
    // policies, power policy etc)
    //
    // Applications may choose to skip this step if the developer is sure
    // that the device is in its desired state at start of applicaton
    //
    // Note that all profiles and persistent settings that were done on the
    // device will be lost
    //
    lRetVal = ConfigureSimpleLinkToDefaultState();
    if(lRetVal < 0)
    {
        if (DEVICE_NOT_IN_STATION_MODE == lRetVal)
        {
            UART_PRINT("Failed to configure the device in its default state, "
                            "Error-code: %d\n\r", DEVICE_NOT_IN_STATION_MODE);
        }

        return -1;
    }

    UART_PRINT("Device is configured in default state \n\r");

    //
    // Assumption is that the device is configured in station mode already
    // and it is in its default state
    //
    lRetVal = sl_Start(0, 0, 0);
    if (lRetVal < 0 || ROLE_STA != lRetVal)
    {
        ASSERT_ON_ERROR(DEVICE_START_FAILED);
    }

    UART_PRINT("Device started as STATION \n\r");

    // Connecting to WLAN AP - Set with static parameters defined at the top
    // After this call we will be connected and have IP address
    lRetVal = WlanConnect();

    UART_PRINT("Connected to the AP: %s\r\n", SSID_NAME);
    return 0;
}

//*****************************************************************************
//
//! Function to connect to HTTP server
//!
//! \param  httpClient - Pointer to HTTP Client instance
//!
//! \return Error-code or SUCCESS
//!
//*****************************************************************************
#define SECURE 1
static int ConnectToHTTPServer(HTTPCli_Handle httpClient)
{
    long lRetVal = -1;
    struct sockaddr_in addr;

#ifdef USE_PROXY
    struct sockaddr_in paddr;
    paddr.sin_family = AF_INET;
    paddr.sin_port = htons(PROXY_PORT);
    paddr.sin_addr.s_addr = sl_Htonl(PROXY_IP);
    HTTPCli_setProxy((struct sockaddr *)&paddr);
#endif

//#ifdef SECURE
//    SlDateTime_t dt;
//
//    /* Set current Date to validate certificate */
//    dt.sl_tm_day = 30;
//    dt.sl_tm_mon = 6;
//    dt.sl_tm_year = 2015;
//    dt.sl_tm_hour = 22;
//    dt.sl_tm_min = 30;
//    dt.sl_tm_sec = 0;
//    sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (unsigned char *)(&dt));
//#endif

    /* Resolve HOST NAME/IP */
    lRetVal = sl_NetAppDnsGetHostByName((signed char *)HOST_NAME,
                                          strlen((const char *)HOST_NAME),
                                          &g_ulDestinationIP,SL_AF_INET);
    if(lRetVal < 0)
    {
        ASSERT_ON_ERROR(GET_HOST_IP_FAILED);
    }

#ifdef SECURE
#define SL_SSL_CA_CERT	"/cert/digicert.crt"
    struct HTTPCli_SecureParams sparams;
    /* Set secure TLS connection  */
    /* Security parameters */
    sparams.method.secureMethod = SL_SO_SEC_METHOD_TLSV1_2;
    sparams.mask.secureMask = SL_SEC_MASK_TLS_RSA_WITH_AES_256_CBC_SHA; //SL_SEC_MASK_SSL_RSA_WITH_RC4_128_SHA;;
    strncpy(sparams.cafile, SL_SSL_CA_CERT, sizeof(SL_SSL_CA_CERT));
    sparams.privkey[0] = 0;
    sparams.cert[0] = 0;
    sparams.dhkey[0] = 0;
    HTTPCli_setSecureParams(&sparams);
#endif
    /* Set up the input parameters for HTTP Connection */
    addr.sin_family = AF_INET;
    addr.sin_port = htons(HOST_PORT);
    addr.sin_addr.s_addr = sl_Htonl(g_ulDestinationIP);

    /* Testing HTTPCli open call: handle, address params only */
    HTTPCli_construct(httpClient);
#ifdef SECURE
    lRetVal = HTTPCli_connect(httpClient, (struct sockaddr *)&addr, HTTPCli_TYPE_TLS, NULL);
#else
    lRetVal = HTTPCli_connect(httpClient, (struct sockaddr *)&addr, 0, NULL);
#endif
    if (lRetVal < 0)
    {
        UART_PRINT("Connection to server failed. error(%d)\n\r", lRetVal);
        //ASSERT_ON_ERROR(SERVER_CONNECTION_FAILED);
    }
    else
    {
        UART_PRINT("Connection to server created successfully\r\n");
    }

    return 0;
}

//*****************************************************************************
//
//! \brief     SMS Door Bell Main Task - Initializes SimpleLink Driver
//!            and Handles UART Commands
//!
//! \param    pvParameters        -    pointer to the task parameter
//!
//! \return  void
//! \note
//! \warning
//
//*****************************************************************************
static void SmsDoorBell(void *pvParameters)
{
    long lRetVal = -1;

    InitializeAppVariables();

    lRetVal = ConnectToAP();
    if(lRetVal < 0)
    {
        LOOP_FOREVER();
    }

    //Initialize Push Botton Switch
    Button_IF_Init(SendSmsInterruptHandler,SendSmsInterruptHandler); //SW2 and SW3 do the same thing, can configure different tasks

//    while(1)
//    {
//    	// We could do other things here to extend the application features
//    }

}


//*****************************************************************************
//
//! Application startup display on UART
//!
//! \param  none
//!
//! \return none
//!
//*****************************************************************************
static void
DisplayBanner(char * AppName)
{
    UART_PRINT("\n\n\n\r");
    UART_PRINT("\t\t *************************************************\n\r");
    UART_PRINT("\t\t      CC3200 %s Application       \n\r", AppName);
    UART_PRINT("\t\t *************************************************\n\n\n\r");
}


//*****************************************************************************
//
//! Board Initialization & Configuration
//!
//! \param  None
//!
//! \return None
//
//*****************************************************************************
static void
BoardInit(void)
{
/* In case of TI-RTOS vector table is initialize by OS itself */
#ifndef USE_TIRTOS
  //
  // Set vector table base
  //
#if defined(ccs) || defined(gcc)
    MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
#endif
#if defined(ewarm)
    MAP_IntVTableBaseSet((unsigned long)&__vector_table);
#endif
#endif
    //
    // Enable Processor
    //
    MAP_IntMasterEnable();
    MAP_IntEnable(FAULT_SYSTICK);

    PRCMCC3200MCUInit();
}


int main()
{
    long lRetVal = -1;

    //
    // Board Initialization
    //
    BoardInit();

    //
    // Configure the pinmux settings for the peripherals exercised
    //
    PinMuxConfig();

    //
    // Configuring UART
    //
    InitTerm();

    //
    // Display banner
    //
    DisplayBanner(APP_NAME);

    //
    // Simplelinkspawntask
    //
    lRetVal = VStartSimpleLinkSpawnTask(SPAWN_TASK_PRIORITY);
    if(lRetVal < 0)
    {
    ERR_PRINT(lRetVal);
    LOOP_FOREVER();
    }

    lRetVal = osi_MsgQCreate(&g_PBQueue,"PBQueue",sizeof(tPushButtonMsg),1);
      if(lRetVal < 0)
      {
      ERR_PRINT(lRetVal);
      LOOP_FOREVER();
      }

	lRetVal = osi_TaskCreate(PushButtonHandler, \
						  (signed char*)"PushButtonHandler", \
						  OSI_STACK_SIZE , NULL, \
						  TASK_PRIORITY+2, &g_PushButtonTask );
	if(lRetVal < 0)
	{
	ERR_PRINT(lRetVal);
	LOOP_FOREVER();
	}

	lRetVal = osi_TaskCreate(SmsDoorBell, (signed char*)"SmsDoorBell", \
							  OSI_STACK_SIZE, \
							  NULL, TASK_PRIORITY+1, NULL );
	if(lRetVal < 0)
	{
	ERR_PRINT(lRetVal);
	LOOP_FOREVER();
	}

	osi_start();

	while(1)
	{

	}



}

