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

static uint8_t Analog_ToPercent(uint16_t raw)
{
    uint32_t clamped = raw;

    if (clamped > APP_ANALOG_MAX_RAW)
    {
        clamped = APP_ANALOG_MAX_RAW;
    }

    return (uint8_t)((clamped * 100U) / APP_ANALOG_MAX_RAW);
}

void SlaveInputs_Init(void)
{
    for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
    {
        g_app.slave_inputs.buttons[i].pressed = Hardware_ReadButton(i);
        g_app.slave_inputs.buttons[i].changed = false;
        g_app.slave_inputs.buttons[i].last_change_ms = Hardware_GetTickMs();
    }

    g_app.slave_inputs.analog.raw = Hardware_ReadAnalogRaw();
    g_app.slave_inputs.analog.filtered = g_app.slave_inputs.analog.raw;
    g_app.slave_inputs.analog.percent = Analog_ToPercent(g_app.slave_inputs.analog.filtered);
}

void SlaveInputs_Process(void)
{
    const uint32_t now = Hardware_GetTickMs();

    for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
    {
        const bool pressed = Hardware_ReadButton(i);
        AppButton_t *button = &g_app.slave_inputs.buttons[i];

        if ((pressed != button->pressed) &&
            ((now - button->last_change_ms) >= APP_BUTTON_DEBOUNCE_MS))
        {
            button->pressed = pressed;
            button->changed = true;
            button->last_change_ms = now;
            g_app.slave_inputs.sequence++;
        }
    }

    const uint16_t raw = Hardware_ReadAnalogRaw();
    AppAnalogChannel_t *analog = &g_app.slave_inputs.analog;
    const uint16_t old_percent = analog->percent;

    analog->raw = raw;
    analog->filtered = (uint16_t)(((uint32_t)analog->filtered * 7U + raw) / 8U);
    analog->percent = Analog_ToPercent(analog->filtered);

    if (analog->percent != old_percent)
    {
        g_app.slave_inputs.sequence++;
    }
}

int SlaveInputs_HasChanges(void)
{
    for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
    {
        if (g_app.slave_inputs.buttons[i].changed)
        {
            return 1;
        }
    }

    return 0;
}

void SlaveInputs_ClearChanges(void)
{
    for (uint8_t i = 0U; i < APP_BUTTON_COUNT; i++)
    {
        g_app.slave_inputs.buttons[i].changed = false;
    }
}
