/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2019 Google LLC.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "AppTask.h"
#include "AppConfig.h"
#include "AppEvent.h"
#include "ColorFormat.h"
#include "LEDWidget.h"

#include "qrcodegen.h"

#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/attribute-type.h>
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-id.h>
#include <app/clusters/identify-server/identify-server.h>
#include <app/clusters/network-commissioning/network-commissioning.h>
#include <app/clusters/on-off-server/on-off-server.h>
#include <app/server/OnboardingCodesUtil.h>
#include <app/server/Server.h>
#include <app/util/attribute-storage.h>

#include <assert.h>

#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>

#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <setup_payload/SetupPayload.h>

#include <lib/support/CodeUtils.h>

#include <platform/CHIPDeviceLayer.h>
#include <platform/mt793x/NetworkCommissioningWiFiDriver.h>

#if defined(ENABLE_CHIP_SHELL)
#include "lib/shell/Engine.h"
#include "lib/shell/commands/Help.h"
#endif // ENABLE_CHIP_SHELL

#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
#define APP_TASK_STACK_SIZE (4096)
#define APP_TASK_PRIORITY 2
#define APP_EVENT_QUEUE_SIZE 10
#define EXAMPLE_VENDOR_ID 0xcafe

#ifdef portYIELD_FROM_ISR
#define OS_YIELD_FROM_ISR(yield) portYIELD_FROM_ISR(yield)
#elif portEND_SWITCHING_ISR
#define OS_YIELD_FROM_ISR(yield) portEND_SWITCHING_ISR(yield)
#else
#error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR"
#endif

#define UNUSED_PARAMETER(a) (a = a)

#if defined(ENABLE_CHIP_SHELL)
using chip::Shell::Engine;
using chip::Shell::PrintCommandHelp;
using chip::Shell::shell_command_t;
using chip::Shell::streamer_get;
using chip::Shell::streamer_printf;

using namespace chip::app::Clusters;

Engine sShellLightSubCommands;
Engine sShellLightOnOffSubCommands;

#endif // defined(ENABLE_CHIP_SHELL)

namespace {

TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer.
TaskHandle_t sAppTaskHandle;
QueueHandle_t sAppEventQueue;

LEDWidget sStatusLED;
uint8_t sLightLEDLevelChangedCount = 0;

bool sIsWiFiProvisioned = false;
bool sIsWiFiEnabled     = false;
bool sIsWiFiAttached    = false;

uint8_t sAppEventQueueBuffer[APP_EVENT_QUEUE_SIZE * sizeof(AppEvent)];
StaticQueue_t sAppEventQueueStruct;

StackType_t appStack[APP_TASK_STACK_SIZE * 2 / sizeof(StackType_t)];
StaticTask_t appTaskStruct;

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
using namespace chip::DeviceLayer::NetworkCommissioning;
chip::app::Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */,
                                                                                      &GenioWiFiDriver::GetInstance());
#endif

} // namespace

using namespace chip::TLV;
using namespace ::chip::Credentials;
using namespace ::chip::DeviceLayer;

AppTask AppTask::sAppTask;

#ifdef ENABLE_CHIP_SHELL

/********************************************************
 * Light shell functions
 *********************************************************/

CHIP_ERROR LightHelpHandler(int argc, char ** argv)
{
    sShellLightSubCommands.ForEachCommand(PrintCommandHelp, nullptr);
    return CHIP_NO_ERROR;
}

CHIP_ERROR LightCommandHandler(int argc, char ** argv)
{
    if (argc == 0)
    {
        return LightHelpHandler(argc, argv);
    }

    return sShellLightSubCommands.ExecCommand(argc, argv);
}

/********************************************************
 * OnOff switch shell functions
 *********************************************************/

CHIP_ERROR OnOffHelpHandler(int argc, char ** argv)
{
    sShellLightOnOffSubCommands.ForEachCommand(PrintCommandHelp, nullptr);
    return CHIP_NO_ERROR;
}

CHIP_ERROR OnOffLightCommandHandler(int argc, char ** argv)
{
    if (argc == 0)
    {
        return OnOffHelpHandler(argc, argv);
    }

    return sShellLightOnOffSubCommands.ExecCommand(argc, argv);
}

CHIP_ERROR OnLightCommandHandler(int argc, char ** argv)
{
    GetAppTask().PostLightActionRequest(0, LightingManager::ON_ACTION, 0);
    return CHIP_NO_ERROR;
}

CHIP_ERROR OffLightCommandHandler(int argc, char ** argv)
{
    GetAppTask().PostLightActionRequest(0, LightingManager::OFF_ACTION, 0);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ColorLightCommandHandler(int argc, char ** argv)
{
    uint32_t rgb = 0;

    if (argc < 3)
    {
        return LightHelpHandler(argc, argv);
    }

    rgb = (atoi(argv[2]) << 16) | (atoi(argv[1]) << 8) | atoi(argv[0]);
    MT793X_LOG("ColorLightCommandHandler: %x", rgb);

    GetAppTask().PostLightActionRequest(0, LightingManager::COLOR_ACTION, rgb);
    return CHIP_NO_ERROR;
}

CHIP_ERROR LevelLightCommandHandler(int argc, char ** argv)
{
    uint8_t level = 0;
    if (argc < 1)
    {
        return LightHelpHandler(argc, argv);
    }

    level = atoi(argv[0]);
    MT793X_LOG("LevelLightCommandHandler: %d", level);
    GetAppTask().PostLightActionRequest(0, LightingManager::LEVEL_ACTION, level);
    return CHIP_NO_ERROR;
}

/********************************************************
 * Occupancy sensor simulation shell functions
 *********************************************************/

CHIP_ERROR OccuPresentLightCommandHandler(int argc, char ** argv)
{
    GetAppTask().OccupancyHandler(true);
    return CHIP_NO_ERROR;
}

CHIP_ERROR OccuClearLightCommandHandler(int argc, char ** argv)
{
    GetAppTask().OccupancyHandler(false);
    return CHIP_NO_ERROR;
}

/********************************************************
 * Register all light commands
 *********************************************************/

/**
 * @brief configures lighting-app matter shell
 *
 */
static void RegisterLightCommands()
{
    static const shell_command_t sLightSubCommands[] = {
        {
            .cmd_func = LightHelpHandler,
            .cmd_name = "help",
            .cmd_help = "Usage: light <subcommand>",
        },
        {
            .cmd_func = OnOffLightCommandHandler,
            .cmd_name = "onoff",
            .cmd_help = "Usage: light onoff <subcommand>",
        },
        {
            .cmd_func = ColorLightCommandHandler,
            .cmd_name = "color",
            .cmd_help = "Usage: light color <r:0~255> <g:0~255> <b:0~255>",
        },
        {
            .cmd_func = LevelLightCommandHandler,
            .cmd_name = "level",
            .cmd_help = "Usage: light level <level:0~100>",
        },
        {
            .cmd_func = OccuPresentLightCommandHandler,
            .cmd_name = "present",
            .cmd_help = "Sends occupancy present event to lighting app",
        },
        {
            .cmd_func = OccuClearLightCommandHandler,
            .cmd_name = "clear",
            .cmd_help = "Sends occupancy clear to lighting app",
        },
    };

    static const shell_command_t sLightOnOffSubCommands[] = {
        {
            .cmd_func = OnOffHelpHandler,
            .cmd_name = "help",
            .cmd_help = "Usage : light ononff <subcommand>",
        },
        {
            .cmd_func = OnLightCommandHandler,
            .cmd_name = "on",
            .cmd_help = "Sends on command to lighting app",
        },
        {
            .cmd_func = OffLightCommandHandler,
            .cmd_name = "off",
            .cmd_help = "Sends off command to lighting app",
        },
    };

    static const shell_command_t sLightCommand[] = {
        {
            .cmd_func = LightCommandHandler,
            .cmd_name = "light",
            .cmd_help = "Lighting-app commands. Usage: light <subcommand>",
        },
    };

    sShellLightOnOffSubCommands.RegisterCommands(sLightOnOffSubCommands, ArraySize(sLightOnOffSubCommands));
    sShellLightSubCommands.RegisterCommands(sLightSubCommands, ArraySize(sLightSubCommands));

    Engine::Root().RegisterCommands(sLightCommand, ArraySize(sLightCommand));
}
#endif // ENABLE_CHIP_SHELL

CHIP_ERROR AppTask::StartAppTask()
{
    sAppEventQueue = xQueueCreateStatic(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent), sAppEventQueueBuffer, &sAppEventQueueStruct);
    if (sAppEventQueue == NULL)
    {
        MT793X_LOG("Failed to allocate app event queue");
        appError(APP_ERROR_EVENT_QUEUE_FAILED);
    }

    // Start App task.
    sAppTaskHandle = xTaskCreateStatic(AppTaskMain, APP_TASK_NAME, ArraySize(appStack), NULL, 1, appStack, &appTaskStruct);
    if (sAppTaskHandle == nullptr)
        return APP_ERROR_CREATE_TASK_FAILED;

    return CHIP_NO_ERROR;
}

CHIP_ERROR AppTask::Init()
{
    CHIP_ERROR error = CHIP_NO_ERROR;

    sLightLEDLevelChangedCount = 0;

    // Wait for the WiFi to be initialized
    MT793X_LOG("APP: Wait WiFi Init");
    vTaskDelay(1000); // TODO
    MT793X_LOG("APP: Done WiFi Init");

#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
    sWiFiNetworkCommissioningInstance.Init();
#endif

    // Init ZCL Data Model and start server
    static chip::CommonCaseDeviceServerInitParams initParams;
    (void) initParams.InitializeStaticResourcesBeforeServerInit();
    chip::Server::GetInstance().Init(initParams);

    // Initialize device attestation config
    SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());

    // Create FreeRTOS sw timer for Function Selection.
    sFunctionTimer = xTimerCreate("FnTmr",          // Just a text name, not used by the RTOS kernel
                                  1,                // == default timer period (mS)
                                  false,            // no timer reload (==one-shot)
                                  (void *) this,    // init timer id = app task obj context
                                  TimerEventHandler // timer callback handler
    );
    if (sFunctionTimer == NULL)
    {
        MT793X_LOG("funct timer create failed");
        appError(APP_ERROR_CREATE_TIMER_FAILED);
    }

    MT793X_LOG("Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
    error = LightMgr().Init();
    if (error != CHIP_NO_ERROR)
    {
        MT793X_LOG("LightMgr Init failed");
        appError(error);
    }

    LightMgr().SetCallbacks(ActionInitiated, ActionCompleted);

    sStatusLED.Init(LED_STATUS);

    ConfigurationMgr().LogDeviceConfig();

    // PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE));
    PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kSoftAP));

#if defined(ENABLE_CHIP_SHELL)
    RegisterLightCommands();
#endif

    return error;
}

void AppTask::AppTaskMain(void * pvParameter)
{
    AppEvent event;

    CHIP_ERROR error = sAppTask.Init();
    if (error != CHIP_NO_ERROR)
    {
        MT793X_LOG("AppTask.Init() failed");
        appError(error);
    }

    MT793X_LOG("AppTask started");

    while (true)
    {
        BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10));
        while (eventReceived == pdTRUE)
        {
            sAppTask.DispatchEvent(&event);
            eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
        }

        // Collect connectivity and configuration state from the CHIP stack. Because
        // the CHIP event loop is being run in a separate task, the stack must be
        // locked while these values are queried.  However we use a non-blocking
        // lock request (TryLockCHIPStack()) to avoid blocking other UI activities
        // when the CHIP task is busy (e.g. with a long crypto operation).
        if (PlatformMgr().TryLockChipStack())
        {
            sIsWiFiProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
            sIsWiFiEnabled     = ConnectivityMgr().IsWiFiStationEnabled();
            sIsWiFiAttached    = ConnectivityMgr().IsWiFiStationConnected();

            PlatformMgr().UnlockChipStack();
        }

        // Update the status LED if factory reset has not been initiated.
        //
        // If system has "full connectivity", keep the LED On constantly.
        //
        // If thread and service provisioned, but not attached to the thread network
        // yet OR no connectivity to the service OR subscriptions are not fully
        // established THEN blink the LED Off for a short period of time.
        //
        // If the system has ble connection(s) uptill the stage above, THEN blink
        // the LEDs at an even rate of 100ms.
        //
        // Otherwise, blink the LED ON for a very short time.
        if (sAppTask.mFunction != kFunction_FactoryReset)
        {
            if (sIsWiFiProvisioned && sIsWiFiEnabled && !sIsWiFiAttached)
            {
                sStatusLED.Blink(950, 50);
            }
            else
            {
                sStatusLED.Blink(50, 950);
            }
        }
    }
}

void AppTask::LightActionEventHandler(AppEvent * aEvent)
{
    bool initiated = false;
    LightingManager::Action_t action;
    int32_t actor;
    CHIP_ERROR err = CHIP_NO_ERROR;
    uint8_t level  = 0;

    if (aEvent->Type == AppEvent::kEventType_Light)
    {
        action = static_cast<LightingManager::Action_t>(aEvent->LightEvent.Action);
        actor  = aEvent->LightEvent.Actor;
        level  = aEvent->LightEvent.Value;
    }
    else if (aEvent->Type == AppEvent::kEventType_Button)
    {
        if (LightMgr().IsLightOn() && sLightLEDLevelChangedCount >= 4)
        {
            sLightLEDLevelChangedCount = 1;
            action                     = LightingManager::OFF_ACTION;
        }
        else if (LightMgr().IsLightOn() && sLightLEDLevelChangedCount < 4)
        {
            sLightLEDLevelChangedCount += 1;
            action = LightingManager::LEVEL_ACTION;
        }
        else
        {
            action = LightingManager::ON_ACTION;
        }
        actor = AppEvent::kEventType_Button;
        level = sLightLEDLevelChangedCount * 25;
    }
    else
    {
        err = APP_ERROR_UNHANDLED_EVENT;
    }

    if (err == CHIP_NO_ERROR)
    {
        if (action == LightingManager::COLOR_ACTION)
        {
            RgbColor_t rbg;
            uint32_t rbg_raw = aEvent->LightEvent.Value;
            rbg.r            = rbg_raw & 0xFF;
            rbg.g            = (rbg_raw & 0xFF00) >> 8;
            rbg.b            = (rbg_raw & 0xFF0000) >> 16;
            initiated        = LightMgr().InitiateAction(AppEvent::kEventType_Light, action, (uint8_t *) &rbg);
        }
        else
        {
            MT793X_LOG("Lighting level: %d", level);
            initiated = LightMgr().InitiateAction(AppEvent::kEventType_Light, action, &level);
        }

        if (!initiated)
        {
            MT793X_LOG("Action is already in progress or active.");
        }
    }
}

void AppTask::ButtonTimerEventHandler(AppEvent * aEvent)
{
    if (aEvent->Type != AppEvent::kEventType_Timer || sAppTask.mFunctionTimerActive == false)
    {
        return;
    }

    switch (sAppTask.mFunction)
    {
    case kFunction_NoneSelected:
        break;

    case kFunction_LightSwitch:
        // Start timer for user to cancel the facotry reset, if needed
        MT793X_LOG("Factory Reset Triggered.");
        MT793X_LOG("Release button within %ums to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
        sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
        sAppTask.mFunction = kFunction_FactoryReset;

        // Turn off all LEDs before starting blink to make sure blink is
        // co-ordinated.
        sStatusLED.Set(false);
        sStatusLED.Blink(500);
        break;

    case kFunction_FactoryReset:
        MT793X_LOG("Factory Reset Start.");
        // Actually trigger Factory Reset
        sAppTask.mFunction = kFunction_NoneSelected;
        ConfigurationMgr().InitiateFactoryReset();
        sStatusLED.Set(true);
        break;

    default:
        break;
    }
}

void AppTask::OccupancyEventHandler(AppEvent * aEvent)
{
    if (aEvent->Type != AppEvent::kEventType_Occupancy)
    {
        MT793X_LOG("A Non Occupancy received %d", aEvent->Type);
        return;
    }

    uint8_t attributeValue = aEvent->OccupancytEvent.Present ? 1 : 0;

    MT793X_LOG("Lighting occupancy: %u", attributeValue);

    OccupancySensing::Attributes::Occupancy::Set(1, attributeValue);
}

void AppTask::SingleButtonEventHandler(AppEvent * aEvent)
{
    if (aEvent->Type != AppEvent::kEventType_Button)
    {
        MT793X_LOG("A Non ButtonEvent received %d", aEvent->Type);
        return;
    }

    if (aEvent->ButtonEvent.Pressed)
    {
        if (sAppTask.mFunctionTimerActive == false)
        {
            /* Start the timer to detect how long Button has been pressed */
            MT793X_LOG("AppTask status LED on");
            sStatusLED.Set(true);
            sAppTask.mFunction = kFunction_LightSwitch;
            sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
        }
        else
        {
            MT793X_LOG("AppTask function timer already started");
        }
    }
    else
    {
        /* Cancel the timer to detect how long Button has been pressed */
        sAppTask.CancelTimer();

        switch (sAppTask.mFunction)
        {
        case kFunction_LightSwitch:
            MT793X_LOG("AppTask light switch");
            AppEvent event;
            event.Type = AppEvent::kEventType_Button;
            LightActionEventHandler(&event);
            break;
        case kFunction_FactoryReset:
            // factory reset cancelled, restore LED
            MT793X_LOG("AppTask factory reset cancelled");
            break;
        default:
            MT793X_LOG("not handled key release event, mFunction = %x", sAppTask.mFunction);
            break;
        }

        sStatusLED.Set(false);

        sAppTask.mFunction = kFunction_NoneSelected;
    }
}

void AppTask::OccupancyHandler(bool present)
{
    AppEvent occupancy_event                = {};
    occupancy_event.Type                    = AppEvent::kEventType_Occupancy;
    occupancy_event.OccupancytEvent.Present = present;
    occupancy_event.Handler                 = OccupancyEventHandler;
    sAppTask.PostEvent(&occupancy_event);
}

void AppTask::ButtonHandler(const filogic_button_t & button)
{
    AppEvent button_event            = {};
    button_event.Type                = AppEvent::kEventType_Button;
    button_event.ButtonEvent.Pressed = button.press;
    button_event.Handler             = SingleButtonEventHandler;
    sAppTask.PostEvent(&button_event);
}

void AppTask::TimerEventHandler(TimerHandle_t xTimer)
{
    AppEvent event;
    event.Type               = AppEvent::kEventType_Timer;
    event.TimerEvent.Context = (void *) xTimer;
    event.Handler            = ButtonTimerEventHandler;
    sAppTask.PostEvent(&event);
}

void AppTask::CancelTimer()
{
    if (xTimerStop(sFunctionTimer, 0) == pdFAIL)
    {
        MT793X_LOG("app timer stop() failed");
        appError(APP_ERROR_STOP_TIMER_FAILED);
    }

    mFunctionTimerActive = false;
}

void AppTask::StartTimer(uint32_t aTimeoutInMs)
{
    if (xTimerIsTimerActive(sFunctionTimer))
    {
        MT793X_LOG("app timer already started!");
        CancelTimer();
    }

    // timer is not active, change its period to required value (== restart).
    // FreeRTOS- Block for a maximum of 100 ticks if the change period command
    // cannot immediately be sent to the timer command queue.
    if (xTimerChangePeriod(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
    {
        MT793X_LOG("app timer start() failed");
        appError(APP_ERROR_START_TIMER_FAILED);
    }

    mFunctionTimerActive = true;
}

void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor)
{
    // Action initiated, update the light led
    if (aAction == LightingManager::ON_ACTION)
    {
        MT793X_LOG("Turning light ON")
    }
    else if (aAction == LightingManager::OFF_ACTION)
    {
        MT793X_LOG("Turning light OFF")
    }
    else if (aAction == LightingManager::LEVEL_ACTION)
    {
        MT793X_LOG("Changing light level")
    }
    else if (aAction == LightingManager::COLOR_ACTION)
    {
        MT793X_LOG("Changing light color")
    }
}

void AppTask::ActionCompleted(LightingManager::Action_t aAction)
{
    // action has been completed bon the light
    if (aAction == LightingManager::ON_ACTION)
    {
        MT793X_LOG("Light ON")
    }
    else if (aAction == LightingManager::OFF_ACTION)
    {
        MT793X_LOG("Light OFF")
    }
    else if (aAction == LightingManager::LEVEL_ACTION)
    {
        MT793X_LOG("Light level changed")
    }
    else if (aAction == LightingManager::COLOR_ACTION)
    {
        MT793X_LOG("Light color changed")
    }
}

void AppTask::PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction, uint32_t uValue)
{
    AppEvent event;
    event.Type              = AppEvent::kEventType_Light;
    event.LightEvent.Actor  = aActor;
    event.LightEvent.Action = aAction;
    event.LightEvent.Value  = uValue;
    event.Handler           = LightActionEventHandler;
    PostEvent(&event);
}

void AppTask::PostEvent(const AppEvent * aEvent)
{
    if (sAppEventQueue != NULL)
    {
        BaseType_t status;
        if (xPortIsInsideInterrupt())
        {
            BaseType_t higherPrioTaskWoken;

            higherPrioTaskWoken = pdFALSE;
            status              = xQueueSendFromISR(sAppEventQueue, aEvent, &higherPrioTaskWoken);
            OS_YIELD_FROM_ISR(higherPrioTaskWoken);
        }
        else
        {
            status = xQueueSend(sAppEventQueue, aEvent, 1);
        }

        if (!status)
            MT793X_LOG("Failed to post event to app task event queue");
    }
    else
    {
        MT793X_LOG("Event Queue is NULL should never happen");
    }
}

void AppTask::DispatchEvent(AppEvent * aEvent)
{
    if (aEvent->Handler)
    {
        aEvent->Handler(aEvent);
    }
    else
    {
        MT793X_LOG("Event received with no handler. Dropping event.");
    }
}
