/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2023 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#define WIFI_SECURITY_LENGTH  63

/* Common Wi-Fi parameters */
#ifndef WIFI_SSID
#define WIFI_SSID "nxp_configuration_access_point"
#endif

#ifndef WIFI_PASSWORD
#define WIFI_PASSWORD "NXP0123456789"
#endif

#define WIFI_NETWORK_LABEL "MyWifi"

/* Parameters that apply to AP mode only */
#ifndef WIFI_AP_CHANNEL
#define WIFI_AP_CHANNEL 1
#endif

#define MAX_RETRY_TICKS 50

/*******************************************************************************
 * Includes
 ******************************************************************************/

#include <stdio.h>

#include "mongoose.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "timers.h"

#include "wpl.h"

#include "fsl_debug_console.h"


#include "fsl_power.h"
/*******************************************************************************
 * Prototypes
 ******************************************************************************/

static uint32_t SetBoardToClient();
static uint32_t SetBoardToAP();
static uint32_t CleanUpAP();
static uint32_t CleanUpClient();

/*******************************************************************************
 * Definitions
 ******************************************************************************/

typedef enum board_wifi_states
{
    WIFI_STATE_CLIENT,
    WIFI_STATE_CONNECTING,
    WIFI_STATE_CLIENT_SCAN,
    WIFI_STATE_AP,
    WIFI_STATE_AP_SCAN,
} board_wifi_states;

struct board_state_variables
{
    board_wifi_states wifiState;
    char ssid[32];
    char password[32];
    char security[WIFI_SECURITY_LENGTH];
    bool connected;
    TaskHandle_t mainTask;
};

/*******************************************************************************
 * Variables
 ******************************************************************************/
struct board_state_variables g_BoardState;

/*******************************************************************************
 * Code
 ******************************************************************************/
/*
		ssids = WPL_Scan();
        Add Wi-Fi network
        if (strstr(posted_security, "WPA3_SAE"))        {
            result = WPL_AddNetworkWithSecurity(posted_ssid, posted_passphrase, WIFI_NETWORK_LABEL, WPL_SECURITY_WPA3_SAE);
        }        else        {
            result = WPL_AddNetworkWithSecurity(posted_ssid, posted_passphrase, WIFI_NETWORK_LABEL, WPL_SECURITY_WILDCARD);
        }
        
         Initiate joining process
        PRINTF("[i] Joining: %s\r\n", posted_ssid);
        result = WPL_Join(WIFI_NETWORK_LABEL);

        WPL_RemoveNetwork(WIFI_NETWORK_LABEL);
        Get new client address to be sent back to the old browser session
        WPL_GetIP(ip, 1);
        PRINTF(" Now join that network on your device and connect to this IP: %s\r\n", ip);


*/

static void LinkStatusChangeCallback(bool linkState)
{
    if (linkState == false)    {
        // link down
    }    else    {
        // link up
    }
}

static void main_task(void *arg)
{
    uint32_t result = 1;

    PRINTF(
        "\r\n"
        "Starting webconfig DEMO\r\n");

    /* When the App starts up, it will first read the mflash to check if any
     * credentials have been saved from previous runs.
     * If the mflash is empty, the board starts and AP allowing the user to configure
     * the desired Wi-Fi network.
     * Otherwise the stored credentials will be used to connect to the Wi-Fi network.*/
    char ssid[32];
    char password[32];
    char security[WIFI_SECURITY_LENGTH];

//        strcpy(g_BoardState.ssid, ssid);
//        strcpy(g_BoardState.password, password);
//        strcpy(g_BoardState.security, security);
        /* No credentials are stored, the board will start its own AP */
//        strcpy(g_BoardState.ssid, WIFI_SSID);
//        strcpy(g_BoardState.password, WIFI_PASSWORD);
//        g_BoardState.wifiState = WIFI_STATE_AP;

    g_BoardState.connected = false;

    /* Initialize Wi-Fi board */

    /*result =*/ WPL_Init();

//    result = WPL_Start(LinkStatusChangeCallback);

    /* Start WebServer */
    // xTaskCreate(http_srv_task, "http_srv_task", HTTPD_STACKSIZE, NULL, HTTPD_PRIORITY, NULL);

    /* Main Loop */
    while (1)    {
        /* The SetBoardTo<state> function will configure the board Wifi to that given state.
         * After that, this task will suspend itself. It will remain suspended until it is time
         * to switch the state again. Uppon resuming, it will clean up the current state.
         * Every time the Wi-Fi state changes, this loop will perform an iteration switching back
         * and fourth between the two states as required.
         */
        switch (g_BoardState.wifiState)
        {
            case WIFI_STATE_CLIENT:
                SetBoardToClient();
                /* Suspend here until its time to swtich back to AP */
                vTaskSuspend(NULL);
                CleanUpClient();
                break;
            case WIFI_STATE_AP:
            default:
                SetBoardToAP();
                /* Suspend here until its time to stop the AP */
                vTaskSuspend(NULL);
                CleanUpAP();
        }
    }
}

/* Initialize and start local AP */
static uint32_t SetBoardToAP()
{
    uint32_t result;

    /* Set the global ssid and password to the default AP ssid and password */
    strcpy(g_BoardState.ssid, WIFI_SSID);
    strcpy(g_BoardState.password, WIFI_PASSWORD);

    /* Start the access point */
    PRINTF("Starting Access Point: SSID: %s, Chnl: %d\r\n", g_BoardState.ssid, WIFI_AP_CHANNEL);
    //result = WPL_Start_AP(g_BoardState.ssid, g_BoardState.password, WIFI_AP_CHANNEL);

    g_BoardState.connected = true;

    char ip[16];
   // WPL_GetIP(ip, 0);
    PRINTF(" Now join that network on your device and connect to this IP: %s\r\n", ip);

    return 0;
}

/* Clean up the local AP after waiting for all tasks to clean up */
static uint32_t CleanUpAP()
{
    /* Give time for reply message to reach the web interface before destorying the conection */
    vTaskDelay(10000 / portTICK_PERIOD_MS);

    //WPL_Stop_AP();

    return 0;
}

/* Connect to the external AP in g_BoardState.ssid */
static uint32_t SetBoardToClient()
{
    int32_t result;
    // If we are already connected, skip the initialization
    if (!g_BoardState.connected)    {
        /* Add Wi-Fi network */
        if (strstr(g_BoardState.security, "WPA3_SAE"))        {
            //result = WPL_AddNetworkWithSecurity(g_BoardState.ssid, g_BoardState.password, WIFI_NETWORK_LABEL, WPL_SECURITY_WPA3_SAE);
        }        else        {
            //result = WPL_AddNetworkWithSecurity(g_BoardState.ssid, g_BoardState.password, WIFI_NETWORK_LABEL, WPL_SECURITY_WILDCARD);
        }
        //    result = WPL_Join(WIFI_NETWORK_LABEL);

            g_BoardState.connected = true;
            // WPL_GetIP(ip, 1);
    }
    return 0;
}

/* Wait for any transmissions to finish and clean up the Client connection */
static uint32_t CleanUpClient()
{
    /* Give time for reply message to reach the web interface before destroying the connection */
    vTaskDelay(1000 / portTICK_PERIOD_MS);

    /* Leave the external AP */
    //WPL_Leave();
    /* Remove the network profile */
    // WPL_RemoveNetwork(WIFI_NETWORK_LABEL);
    return 0;
}
/*!
 * @brief Main function.
 */
int main(void)
{
    /* Initialize the hardware */
    BOARD_InitBootPins();
    if (BOARD_IS_XIP())
    {
        BOARD_BootClockLPR();
        CLOCK_EnableClock(kCLOCK_Otp);
        CLOCK_EnableClock(kCLOCK_Els);
        CLOCK_EnableClock(kCLOCK_ElsApb);
        RESET_PeripheralReset(kOTP_RST_SHIFT_RSTn);
        RESET_PeripheralReset(kELS_APB_RST_SHIFT_RSTn);
    }
    else
    {
        BOARD_InitBootClocks();
    }
    BOARD_InitDebugConsole();
    /* Reset GMDA */
    RESET_PeripheralReset(kGDMA_RST_SHIFT_RSTn);
    /* Keep CAU sleep clock here. */
    /* CPU1 uses Internal clock when in low power mode. */
    POWER_ConfigCauInSleep(false);
    BOARD_InitSleepPinConfig();

    /* Create the main Task */
    if (xTaskCreate(main_task, "main_task", 2048, NULL, configMAX_PRIORITIES - 4, &g_BoardState.mainTask) != pdPASS)
    {
        PRINTF("[!] MAIN Task creation failed!\r\n");
        while (1)
            ;
    }

    /* Run RTOS */
    vTaskStartScheduler();

    /* Should not reach this statement */
    for (;;)
        ;
}
