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


#include <eCxx/eCxx_Server.h>

#include "NodeMCU_Common.h"


//
// The web server
//
static eCxx::WebServer webServer(80);


//
// 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
    App::uart().begin(9600);

    // Intialize web server
#if __GNUC__ >= 5
    #define WPSTR PGM_STR
#else
    // Workaround for compile error in older versions of GCC
    #define WPSTR
#endif

    webServer.onNotFound( []() {
        // Send response
        webServer.send(404, "text/plain", "Not found");
        // Write to UART
        App::uart().writeStringln( PGM_STR("\nwebServer.onNotFound()") );
        App::uart().writeStringln( webServer.uri()                     );
    } );

    webServer.on( "/", eCxx::HTTPRequestMethod::Get, []() {
        // Send response
        webServer.send(200, WPSTR("text/html"), WPSTR(
            R"EOF(
                <!DOCTYPE html>
                <html>
                    <head>
                        <title>ESP8266 Web Server File Upload handling</title>
                        <style>
                            body {
                                font-family      : Arial, Helvetica, Sans-Serif;
                                color            : #000088;
                                background-color : #CCCCCC;
                            }
                        </style>
                    </head>
                    <body>
                        <form method='post' enctype='multipart/form-data'>
                            <input type='file' name='MyFile'>
                            <br><br>
                            <input type='submit' value='Upload'>
                        </form>
                    </body>
                </html>
            )EOF"
        ) );
        // Write to UART
        App::uart().writeStringln( PGM_STR("\nwebServer.on(\"/\")") );
    } );

    webServer.on(
        "/",
        eCxx::HTTPRequestMethod::Post,
        []() {
            // Tell the client that the server is ready to receive the file upload
            webServer.send(200);
        },
        []() {
            // Get the upload structure
            const auto& upload = webServer.httpUpload();
            // Handle based on the status
            switch(upload.status) {
                case eCxx::HTTPUploadStatus::FileStart:
                    App::uart().writeString   ( PGM_STR("\nwebServer.on(\"/\") - FileStart contentLength=") );
                    App::uart().writeDecString( upload.contentLength                                        );
                    App::uart().writeString   ( PGM_STR(" bytes ; name='")                                  );
                    App::uart().writeString   ( upload.name                                                 );
                    App::uart().writeString   ( PGM_STR("' ; type='")                                       );
                    App::uart().writeString   ( upload.type                                                 );
                    App::uart().writeString   ( PGM_STR("' ; fileName='")                                   );
                    App::uart().writeString   ( upload.fileName                                             );
                    App::uart().writeString   ( PGM_STR("'\n")                                              );
                    break;
                case eCxx::HTTPUploadStatus::FileWrite:
                    // NOTE : The current upload data can be accessed via 'upload.buffer'
                    App::uart().writeString   ( PGM_STR("\nwebServer.on(\"/\") - FileWrite [") );
                    App::uart().writeDecString( upload.currentSize                             );
                    App::uart().writeString   ( PGM_STR(" bytes] => [")                        );
                    App::uart().writeDecString( upload.totalSize                               );
                    App::uart().writeStringln ( PGM_STR(" bytes]")                             );
                    break;
                case eCxx::HTTPUploadStatus::FileEnd:
                    webServer.send(200, "text/plain", "OK");
                    App::uart().writeStringln( PGM_STR("\nwebServer.on(\"/\") - FileEnd") );
                    break;
                case eCxx::HTTPUploadStatus::FileAborted:
                    App::uart().writeStringln( PGM_STR("\nwebServer.on(\"/\") - FileAborted") );
                    break;
            }
        }
    );

    webServer.begin();
}


//
// The task function
//
void eCxx_user_task()
{
    // Process event
    eCxx::Application::processEvent();

    // Handle the web server client
    webServer.handleClient();
}
