/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#include <eCxx/eCxx.h>
#include <eCxx/TZName.h>

#include "NodeMCU_Common.h"


//
// Access point setting
//
// NOTE : Change this to match your access point setting
//
#if !defined(AP_SSID) || !defined(AP_PASS)
    #define AP_SSID "<your_ap_ssid>"
    #define AP_PASS "<your_ap_passphrase>"
#endif


//
// Timezone setting
//
// NOTE : Change this to match your timezone
//
#ifndef TIMEZONE_NAME
    #define TIMEZONE_NAME eCxx::TZ::Etc_Greenwich
#endif


//
// The init function
//
void eCxx_user_init()
{
    // Initialize application
    initBasicNodeMCUApp();

    // There is no need to enable the 74LVC541 buffers on the eCxx NodeMCU development board because
    // the UART is only used for communication with the host PC

    // Initialize UART
    auto& uart = App::uart();
    uart.begin(9600);

    // Print some information
    uart.writeStringln( PGM_STR("\nInitialized as a WiFi access point.\n") );

    // Switch to WiFi station mode
    uart.writeString( PGM_STR("Trying to switch to WiFi station mode ... ") );

    // NOTE : # In a real world application, the SSID and passphrase should be read from
    //          saved configuration data via:
    //              # nvStorageRead       () and nvStorageWrite      (); or
    //              # nvOpenFileForReading() and nvOpenFileForWriting()
    //        # Only if valid SSID and passphrase are found then the system should switch
    //          to station mode.
    //        # In case the switch is failed, the saved SSID and passphrase should be
    //          erased and then the system is restarted via softReset().
    if( !App::switchToWiFiStationMode
        (
            PGM_STR(AP_SSID),
            PGM_STR(AP_PASS)
        )
    ) {
        // OTA programming is unusable here because the WiFi initialization has failed!
        uart.writeStringln( PGM_STR("FAILED\nHalting here!\n" ) );
        App::halt();
    }

    uart.writeStringln( PGM_STR("SUCCESS\n") );

#if 1

    // Set date-time using NTP
    uart.writeString( PGM_STR("Configuring NTP ... ") );

    if( !App::configNTP(TIMEZONE_NAME, "pool.ntp.org") ) {
        uart.writeStringln( PGM_STR("FAILED\nHalting here!\n" ) );
        App::halt();
    }
    uart.writeStringln( PGM_STR("SUCCESS\n") );

    // Example of calling App::configTime() without using timezone name
    // for 7 hours to the west with an enabled 30 minute DST:
    //     App::configNTP(3600 * 7, 3600 / 2, "pool.ntp.org")

#else

    // Set date-time manually
    App::setCurrentDateTime(1577836800000000ULL); // 2020/01/01 00:00:00

#endif
}


//
// The task function
//
void eCxx_user_task()
{
    // Process event and delay
    static eCxx::uint32_t prvMillis = 0;
           eCxx::uint32_t curMillis = App::processEvent();
    if(curMillis - prvMillis < 1000) return;
    else                             prvMillis = curMillis;

    // Get and print the current date and time
    const auto& dt   = App::currentDateTime(); // DateTimeMode::UTC and DateTimeMode::Local (the default parameter)
          auto& uart = App::uart();

    uart.writeDecString(dt.isDST,   eCxx::Convert::NumSign::None_Minus, 1, eCxx::Convert::NumPad::Zero);
    uart.write         (' ');
    uart.writeDecString(dt.yearDay, eCxx::Convert::NumSign::None_Minus, 3, eCxx::Convert::NumPad::Zero);
    uart.write         (' ');
    uart.writeDecString(dt.weekDay, eCxx::Convert::NumSign::None_Minus, 1, eCxx::Convert::NumPad::Zero);
    uart.write         (' ');
    uart.writeDecString(dt.year,    eCxx::Convert::NumSign::None_Minus, 4, eCxx::Convert::NumPad::Zero);
    uart.write         ('/');
    uart.writeDecString(dt.month,   eCxx::Convert::NumSign::None_Minus, 2, eCxx::Convert::NumPad::Zero);
    uart.write         ('/');
    uart.writeDecString(dt.day,     eCxx::Convert::NumSign::None_Minus, 2, eCxx::Convert::NumPad::Zero);
    uart.write         (' ');
    uart.writeDecString(dt.hour,    eCxx::Convert::NumSign::None_Minus, 2, eCxx::Convert::NumPad::Zero);
    uart.write         (':');
    uart.writeDecString(dt.minute,  eCxx::Convert::NumSign::None_Minus, 2, eCxx::Convert::NumPad::Zero);
    uart.write         (':');
    uart.writeDecString(dt.second,  eCxx::Convert::NumSign::None_Minus, 2, eCxx::Convert::NumPad::Zero);
    uart.write         ('\n');
}
