/*
 *
 *    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_matrix.h"

/* Key matrix scanning period */
#define KEY_MATRIX_SCAN_PERIOD_MS 100

/* Poll key matrix and rise event on key change */
static void key_matrix_poll(struct key_matrix_data * key_matrix, bool init)
{
    for (size_t i = 0; i < key_matrix->col_len; i++)
    {
        gpio_pin_configure_dt(&key_matrix->col[i], GPIO_OUTPUT_ACTIVE);
        for (size_t j = 0; j < key_matrix->row_len; j++)
        {
            size_t button_num = i * key_matrix->col_len + j;
            bool pin          = gpio_pin_get_dt(&key_matrix->row[j]);

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

/* Key matrix scan worker */
static void key_matrix_scan_work(struct k_work * item)
{
    struct key_matrix_data * key_matrix = CONTAINER_OF(item, struct key_matrix_data, work);

    (void) k_work_schedule(&key_matrix->work, K_MSEC(KEY_MATRIX_SCAN_PERIOD_MS));
    key_matrix_poll(key_matrix, false);
}

/* Public APIs */

bool key_matrix_init(struct key_matrix_data * key_matrix)
{
    bool result = true;

    do
    {
        if (!key_matrix->col_len || !key_matrix->row_len)
        {
            result = false;
            break;
        }
        /* check if all GPIOs are ready */
        for (size_t i = 0; i < key_matrix->col_len; i++)
        {
            if (!gpio_is_ready_dt(&key_matrix->col[i]))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        for (size_t i = 0; i < key_matrix->row_len; i++)
        {
            if (!gpio_is_ready_dt(&key_matrix->row[i]))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* init all GPIOs are ready */
        for (size_t i = 0; i < key_matrix->col_len; i++)
        {
            if (gpio_pin_configure_dt(&key_matrix->col[i], GPIO_INPUT))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        for (size_t i = 0; i < key_matrix->row_len; i++)
        {
            if (gpio_pin_configure_dt(&key_matrix->row[i], GPIO_INPUT))
            {
                result = false;
                break;
            }
        }
        if (!result)
        {
            break;
        }
        /* set all keys to current state */
        key_matrix_poll(key_matrix, true);
        key_matrix->on_button_change = NULL;
        key_matrix->context          = NULL;
        /* work init */
        k_work_init_delayable(&key_matrix->work, key_matrix_scan_work);
        while (k_work_schedule(&key_matrix->work, K_NO_WAIT) == -EBUSY)
        {
            k_usleep(10); /* Let other stuffs run */
        }
        /* all done */
    } while (0);

    return result;
}

void key_matrix_set_callback(struct key_matrix_data * key_matrix, key_matrix_on_button_change_t on_button_change, void * context)
{
    key_matrix->on_button_change = on_button_change;
    key_matrix->context          = context;
}
