/*
 *
 *    Copyright (c) 2024 Project CHIP Authors
 *
 *    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 "zephyr_led_pool.h"
#include <stdarg.h>
#include <stdlib.h>

/* Auxiliary data to support blink */
struct led_pool_aux_data
{
    enum led_state state;
    k_ticks_t t_event;
    k_timeout_t t_on;
    k_timeout_t t_off;
    bool current_state;
};

/* Get timeout to next event in auxiliary data */
static k_timeout_t led_pool_aux_timeout(const struct led_pool_data * led_pool)
{
    k_timeout_t timeout                           = { .ticks = K_TICKS_FOREVER };
    const struct led_pool_aux_data * led_pool_aux = (const struct led_pool_aux_data *) led_pool->aux;
    size_t led_pool_aux_len                       = led_pool->out_len;

    for (size_t i = 0; i < led_pool_aux_len; i++)
    {
        if (led_pool_aux[i].state == LED_BLINK)
        {
            k_ticks_t t_next = led_pool_aux[i].t_event +
                (led_pool_aux[i].current_state ? led_pool_aux[i].t_on.ticks : led_pool_aux[i].t_off.ticks);
            k_ticks_t t_now  = sys_clock_tick_get();
            k_timeout_t this = { .ticks = t_next > t_now ? t_next - t_now : 0 };
            if (timeout.ticks == K_TICKS_FOREVER || this.ticks < timeout.ticks)
            {
                timeout.ticks = this.ticks;
            }
        }
    }
    return timeout;
}

/* Process events in auxiliary data */
static void led_pool_aux_update(const struct led_pool_data * led_pool)
{
    struct led_pool_aux_data * led_pool_aux = (struct led_pool_aux_data *) led_pool->aux;
    size_t led_pool_aux_len                 = led_pool->out_len;

    for (size_t i = 0; i < led_pool_aux_len; i++)
    {
        if (led_pool_aux[i].state == LED_BLINK)
        {
            k_ticks_t t_next = led_pool_aux[i].t_event +
                (led_pool_aux[i].current_state ? led_pool_aux[i].t_on.ticks : led_pool_aux[i].t_off.ticks);
            k_ticks_t t_now = sys_clock_tick_get();

            if (t_next <= t_now)
            {
                led_pool_aux[i].current_state = !led_pool_aux[i].current_state;
                led_pool_aux[i].t_event       = t_now;
                (void) gpio_pin_set_dt(&led_pool->out[i], led_pool_aux[i].current_state);
            }
        }
    }
}

/* Led pool worker */
static void led_pool_event_work(struct k_work * item)
{
    struct led_pool_data * led_pool = CONTAINER_OF(item, struct led_pool_data, work);

    led_pool_aux_update(led_pool);
    (void) k_work_reschedule(&led_pool->work, led_pool_aux_timeout(led_pool));
}

/* Public APIs */

bool led_pool_init(struct led_pool_data * led_pool)
{
    bool result = true;

    do
    {
        if (!led_pool->out_len)
        {
            result = false;
            break;
        }
        /* check if all GPIOs are ready */
        for (size_t i = 0; i < led_pool->out_len; i++)
        {
            if (!gpio_is_ready_dt(&led_pool->out[i]))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* init all GPIOs are ready */
        for (size_t i = 0; i < led_pool->out_len; i++)
        {
            if (gpio_pin_configure_dt(&led_pool->out[i], GPIO_OUTPUT))
            {
                result = false;
                break;
            }
            if (gpio_pin_set_dt(&led_pool->out[i], 0))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* set auxiliary blink structure */
        struct led_pool_aux_data * led_pool_aux =
            (struct led_pool_aux_data *) malloc(sizeof(struct led_pool_aux_data) * led_pool->out_len);

        if (!led_pool_aux)
        {
            result = false;
            break;
        }

        for (size_t i = 0; i < led_pool->out_len; i++)
        {
            led_pool_aux[i].state = LED_OFF;
        }
        led_pool->aux = led_pool_aux;
        /* init work */
        k_work_init_delayable(&led_pool->work, led_pool_event_work);
        if (k_work_reschedule(&led_pool->work, led_pool_aux_timeout(led_pool)) < 0)
        {
            result = false;
            break;
        }
        /* all done */
    } while (0);

    return result;
}

bool led_pool_set(struct led_pool_data * led_pool, size_t led, enum led_state state, ...)
{
    bool result = false;

    if (led < led_pool->out_len)
    {
        if (state == LED_ON || state == LED_OFF)
        {
            if (!gpio_pin_set_dt(&led_pool->out[led], state))
            {
                struct led_pool_aux_data * led_pool_aux = led_pool->aux;

                led_pool_aux[led].state = state;
                if (k_work_reschedule(&led_pool->work, led_pool_aux_timeout(led_pool)) >= 0)
                {
                    result = true;
                }
            }
        }
        else if (state == LED_BLINK)
        {
            if (!gpio_pin_set_dt(&led_pool->out[led], 1))
            {
                struct led_pool_aux_data * led_pool_aux = led_pool->aux;
                va_list argptr;

                va_start(argptr, state);
                led_pool_aux[led].state         = state;
                led_pool_aux[led].t_event       = sys_clock_tick_get();
                led_pool_aux[led].t_on          = va_arg(argptr, k_timeout_t);
                led_pool_aux[led].t_off         = va_arg(argptr, k_timeout_t);
                led_pool_aux[led].current_state = true;
                va_end(argptr);
                if (k_work_reschedule(&led_pool->work, led_pool_aux_timeout(led_pool)) >= 0)
                {
                    result = true;
                }
            }
        }
    }
    return result;
}
