#include "app_config.h"
#include "app_types.h"
#include "hardware.h"
#include "slave_inputs.h"
#include "zigbee_app.h"
#include "zigbee_port.h"

static void ZigbeeApp_UpdateStatusLed(void)
{
    const uint32_t phase = g_app.uptime_ms % 1000U;
    bool on = false;

    switch (g_app.zigbee_state)
    {
        case APP_ZB_CONNECTED:
            if (g_app.role == APP_ROLE_MASTER)
            {
                on = (phase < 80U);
            }
            else
            {
                on = (phase < 80U) || ((phase >= 160U) && (phase < 240U));
            }
            break;

        case APP_ZB_JOINING:
            on = ((phase % 160U) < 80U);
            break;

        case APP_ZB_ERROR:
            on = ((phase % 100U) < 50U);
            break;

        case APP_ZB_DISCONNECTED:
        default:
            on = ((phase % 400U) < 80U);
            break;
    }

    Hardware_SetRoleLed(on);
}

static void ZigbeeApp_UpdateRoleFromSwitch(void)
{
    const bool role_pin_is_master = Hardware_ReadRoleSwitchIsMaster();
    const AppRole_t requested_role = role_pin_is_master;
       // role_pin_is_master ? APP_ROLE_MASTER : APP_ROLE_SLAVE;

    if (requested_role != g_app.role)
    {
        App_SetRole(requested_role);
        ZigbeePort_Init(&g_app.zigbee, g_app.role);
    }

    App_DebugRefresh(role_pin_is_master ? 1U : 0U);
}

void ZigbeeApp_Init(void)
{
    ZigbeePort_Init(&g_app.zigbee, g_app.role);
    SlaveInputs_Init();

    const bool role_pin_is_master = Hardware_ReadRoleSwitchIsMaster();
    App_DebugRefresh(role_pin_is_master ? 1U : 0U);
    ZigbeeApp_UpdateStatusLed();
}

void ZigbeeApp_Process(void)
{
    g_app.uptime_ms = Hardware_GetTickMs();

    ZigbeeApp_UpdateRoleFromSwitch();
    ZigbeePort_Process();
    ZigbeeApp_UpdateStatusLed();

    if (g_app.role == APP_ROLE_SLAVE)
    {
        SlaveInputs_Process();

        if ((g_app.uptime_ms - g_app.last_report_ms) >= APP_ZIGBEE_REPORT_PERIOD_MS)
        {
            if (ZigbeePort_SendSlaveInputs(&g_app.slave_inputs) == ZIGBEE_PORT_OK)
            {
                g_app.last_report_ms = g_app.uptime_ms;
                SlaveInputs_ClearChanges();
            }
        }
    }
}
