/*
 *
 *    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_key_pool.h"
#include <stdlib.h>

/* Key pool denouncing settle time */
#define KEY_POOL_DEBOUNCING_GUARD_MS 10

/* Auxiliary data to link key pool with pin isr */
struct key_pool_aux_data
{
    struct key_pool_data * key_pool;
    const struct device * port;
    struct gpio_callback callback;
};

/* Auxiliary function to get ports number in pool */
static size_t key_pool_port_number(const struct key_pool_data * key_pool)
{
    size_t port_num = 0;

    for (size_t i = 0; i < key_pool->inp_len; i++)
    {
        bool port_already = false;

        for (size_t j = 0; j < i; j++)
        {
            if (key_pool->inp[i].port == key_pool->inp[j].port)
            {
                port_already = true;
                break;
            }
        }
        if (!port_already)
        {
            port_num++;
        }
    }
    return port_num;
}

/* Poll key pool and rise event on key change */
static void key_pool_poll(struct key_pool_data * key_pool, bool init)
{
    for (size_t i = 0; i < key_pool->inp_len; i++)
    {
        bool pin = gpio_pin_get_dt(&key_pool->inp[i]);

        if (pin != (bool) (key_pool->buttons[i / 8] & BIT(i % 8)))
        {
            WRITE_BIT(key_pool->buttons[i / 8], i % 8, pin);
            if (!init && key_pool->on_button_change)
            {
                key_pool->on_button_change(i, pin, key_pool->context);
            }
        }
    }
}

/* Key pool scan worker */
static void key_pool_event_work(struct k_work * item)
{
    struct key_pool_data * key_pool = CONTAINER_OF(item, struct key_pool_data, work);

    key_pool_poll(key_pool, false);
}

/* Key pool pin isr */
static void key_pool_on_pin_isr(const struct device * dev, struct gpio_callback * cb, uint32_t pins)
{
    struct key_pool_aux_data * key_pool_aux = CONTAINER_OF(cb, struct key_pool_aux_data, callback);

    (void) k_work_reschedule(&key_pool_aux->key_pool->work, K_MSEC(KEY_POOL_DEBOUNCING_GUARD_MS));
}

/* Public APIs */

bool key_pool_init(struct key_pool_data * key_pool)
{
    bool result = true;

    do
    {
        if (!key_pool->inp_len)
        {
            result = false;
            break;
        }
        /* check if all GPIOs are ready */
        for (size_t i = 0; i < key_pool->inp_len; i++)
        {
            if (!gpio_is_ready_dt(&key_pool->inp[i]))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* init all GPIOs are ready */
        for (size_t i = 0; i < key_pool->inp_len; i++)
        {
            if (gpio_pin_configure_dt(&key_pool->inp[i], GPIO_INPUT))
            {
                result = false;
                break;
            }
            if (gpio_pin_interrupt_configure_dt(&key_pool->inp[i], GPIO_INT_EDGE_BOTH))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* add callbacks to all ports */
        struct key_pool_aux_data * key_pool_aux =
            (struct key_pool_aux_data *) malloc(sizeof(struct key_pool_aux_data) * key_pool_port_number(key_pool));

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

        key_pool->aux                  = key_pool_aux;
        size_t key_pool_aux_inited_cnt = 0;

        for (size_t i = 0; i < key_pool->inp_len; i++)
        {
            bool port_found = false;

            for (size_t j = 0; j < key_pool_aux_inited_cnt; j++)
            {
                if (key_pool->inp[i].port == key_pool_aux[j].port)
                {
                    port_found = true;
                    key_pool_aux[j].callback.pin_mask |= BIT(key_pool->inp[i].pin);
                }
            }
            if (!port_found)
            {
                key_pool_aux[key_pool_aux_inited_cnt].key_pool = key_pool;
                key_pool_aux[key_pool_aux_inited_cnt].port     = key_pool->inp[i].port;
                gpio_init_callback(&key_pool_aux[key_pool_aux_inited_cnt].callback, key_pool_on_pin_isr, BIT(key_pool->inp[i].pin));
                key_pool_aux_inited_cnt++;
            }
        }
        for (size_t i = 0; i < key_pool_aux_inited_cnt; i++)
        {
            if (gpio_add_callback(key_pool_aux[i].port, &key_pool_aux[i].callback))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* set all keys to current state */
        key_pool_poll(key_pool, true);
        /* init work */
        k_work_init_delayable(&key_pool->work, key_pool_event_work);
        /* all done */
    } while (0);

    return result;
}

void key_pool_set_callback(struct key_pool_data * key_pool, key_pool_on_button_change_t on_button_change, void * context)
{
    key_pool->on_button_change = on_button_change;
    key_pool->context          = context;
}
