/**
 * @file i2cDrv.c
 * @author Luis Maciel (luis@logpyx.com)
 * @brief
 * @version x.x.x
 * @date 2025-02-13
 *
 * @copyright Copyright LogPyx S/A (c) 2025
 *
 * 	 _
 *	| |    ___   __ _ _ __  _   ___  __
 *	| |   / _ \ / _` | '_ \| | | \ \/ /
 *	| |__| (_) | (_| | |_) | |_| |>  <
 *	|_____\___/ \__, | .__/ \__, /_/\_\
 *                |__|_|    |___/
 *
 *              Logpyx S/A
 */

#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/logging/log.h>
#include <zephyr/devicetree/pinctrl.h>

#include <nrfx_twis.h>

#include "i2cDrv.h"

LOG_MODULE_REGISTER(i2cDrv, LOG_LEVEL_INF);

#define I2C_SLAVE 1

#if I2C_SLAVE
#define TWI_INSTANCE_ID 2
#define I2C2_NODE DT_NODELABEL(i2c2)
#define I2C2_ADDRESS 0x11

static const nrfx_twis_t s_twi = NRFX_TWIS_INSTANCE(TWI_INSTANCE_ID);

static i2cIrqHandler rxDone;

static void twis_event_handler(nrfx_twis_evt_t const *const p_event);
#else
static const struct i2c_dt_spec dev_i2c; // = I2C_DT_SPEC_GET(DT_ALIAS(myesp));
#endif

uint8_t rx_buf[TWI_RX_BUF_LEN];

void i2cDrvIn(uint8_t *txBuffer, uint16_t size)
{
#if I2C_SLAVE
    nrfx_twis_tx_prepare(&s_twi, txBuffer, size);
#else
    i2c_write_dt(&dev_i2c, txBuffer, size);
#endif
}

void i2cDrvInOut(uint8_t *txBuffer, uint16_t txSize, uint8_t *rxBuffer, uint16_t rxSize)
{
#if !I2C_SLAVE
    i2c_write_read_dt(&dev_i2c, txBuffer, txSize, rxBuffer, rxSize);
#endif
}

void i2cDrvOut(uint8_t *rxBuffer, uint16_t size)
{
    ARG_UNUSED(rxBuffer);
    ARG_UNUSED(size);
}

bool i2cDrvIsWaiting4Tx(void)
{
#if I2C_SLAVE
    return nrfx_twis_is_waiting_tx_buff(&s_twi);
#endif
    return false;
}

void i2cDrvInit(i2cIrqHandler cb)
{
#if I2C_SLAVE
    IRQ_CONNECT(DT_IRQN(I2C2_NODE),
                DT_IRQ(I2C2_NODE, priority),
                nrfx_isr,
                nrfx_twis_2_irq_handler,
                0);

    nrfx_twis_config_t twis_config = NRFX_TWIS_DEFAULT_CONFIG(30, 3, I2C2_ADDRESS);
    nrfx_twis_init(&s_twi, &twis_config, twis_event_handler);
    nrfx_twis_enable(&s_twi);
    rxDone = cb;
#else
    while (!i2c_is_ready_dt(&dev_i2c))
    {
        k_msleep(1);
    }
#endif
}

#if I2C_SLAVE

static void twis_event_handler(nrfx_twis_evt_t const *const p_event)
{
    switch (p_event->type)
    {
    case NRFX_TWIS_EVT_READ_REQ:
        if (p_event->data.buf_req)
        {
            // Sending default message
            static uint8_t default_msg[] = {0x01, 0x02, 0x03};
            nrfx_twis_tx_prepare(&s_twi, default_msg, sizeof(default_msg));
            // LOG_INF("Send default value to master");
        }
        break;

    case NRFX_TWIS_EVT_READ_DONE:
        // LOG_INF("Master terminou leitura.");
        break;

    case NRFX_TWIS_EVT_WRITE_REQ:
        if (p_event->data.buf_req)
        {
            // preparar buffer para receber
            // LOG_INF("Request to receive bytes from master", TWI_RX_BUF_LEN);
            nrfx_twis_rx_prepare(&s_twi, rx_buf, TWI_RX_BUF_LEN);
        }
        break;

    case NRFX_TWIS_EVT_WRITE_DONE:
    {
        // terminou de receber dados do master
        // LOG_INF("I2C Slave recebeu %d bytes:", p_event->data.rx_amount);
        // LOG_HEXDUMP_INF(rx_buf, p_event->data.rx_amount, "RX DATA");
        if (rxDone)
        {
            rxDone(rx_buf, p_event->data.rx_amount);
        }
        break;
    }

    case NRFX_TWIS_EVT_READ_ERROR:
    case NRFX_TWIS_EVT_WRITE_ERROR:
    case NRFX_TWIS_EVT_GENERAL_ERROR:
        break;

    default:
        break;
    }
}
#endif