#include <stdio.h>
#include <string.h>
#include "driver/i2c.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_intr_alloc.h"
#include "freertos/semphr.h"

#define ESP_SLAVE_ADDR                     0x30
#define SLAVE_BUFFER                       512
#define I2C_EXAMPLE_SLAVE_SCL_IO           18             /*!<gpio number for i2c slave clock  */
#define I2C_EXAMPLE_SLAVE_SDA_IO           19               /*!<gpio number for i2c slave data */
#define I2C_EXAMPLE_SLAVE_NUM              I2C_NUM_0        /*!<I2C port number for slave dev */
#define I2C_EXAMPLE_SLAVE_TX_BUF_LEN       (2*SLAVE_BUFFER)  /*!<I2C slave tx buffer size */
#define I2C_EXAMPLE_SLAVE_RX_BUF_LEN       (2*SLAVE_BUFFER)  /*!<I2C slave rx buffer size */
#define ACK_CHECK_EN                       0x1              /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS                      0x0              /*!< I2C master will not check ack from slave */
#define ACK_VAL                            0x0              /*!< I2C ack value */
#define NACK_VAL                           0x1              /*!< I2C nack value */

static const char* TAG="info";

QueueHandle_t I2C_event_handle;

SemaphoreHandle_t binSemaphore;


static void i2c_slave_init(){
    int num_of_bytes;
    uint8_t data_read[2]={};
    int i2c_slave_port=I2C_EXAMPLE_SLAVE_NUM;
    i2c_config_t conf_slave={
    .sda_io_num=I2C_EXAMPLE_SLAVE_SDA_IO,
    .sda_pullup_en=GPIO_PULLUP_ENABLE,
    .scl_io_num=I2C_EXAMPLE_SLAVE_SCL_IO,
    .scl_pullup_en=GPIO_PULLUP_ENABLE,
    .mode=I2C_MODE_SLAVE,
    .slave.addr_10bit_en=0,
    .slave.slave_addr=ESP_SLAVE_ADDR,
    .clk_flags=0,
    };
    i2c_param_config(i2c_slave_port, &conf_slave);
    i2c_driver_install(i2c_slave_port,conf_slave.mode,I2C_EXAMPLE_SLAVE_RX_BUF_LEN,I2C_EXAMPLE_SLAVE_TX_BUF_LEN,0);

    while(1){
        ESP_LOGI(TAG,"ESP slave task begining");
        num_of_bytes=i2c_slave_read_buffer(I2C_EXAMPLE_SLAVE_NUM, data_read, 20, 2000 / portTICK_PERIOD_MS);
        if(num_of_bytes>0){

        ESP_LOGI(TAG,"printing bytes");
        for(int i=0;i<sizeof(data_read);i++){
        ESP_LOGI(TAG,"%02x",data_read[i]);
    
        }
        ESP_LOGI(TAG,"-----------------");


        ESP_LOGI(TAG,"num of bytes received %d ",num_of_bytes);

        uint16_t result = ((uint16_t)data_read[0]) | ((uint16_t)data_read[1] << 8);//adding two bytes together
        ESP_LOGI(TAG,"uint16_t data: %d",result);
        I2C_event_handle=xQueueCreate(5,sizeof(result));
        xQueueSendToFront(I2C_event_handle,&result,2000 / portTICK_PERIOD_MS);
        xSemaphoreGive(binSemaphore);

        }
        else{ESP_LOGI(TAG,"I2C bytes not received");}
    }

}

void wifi_ir_http_app(){
    ESP_LOGI(TAG,"ESP wifi&http task begining");
    portBASE_TYPE res;
    int queue_receive_buffer[2]={};
    while(1){
    xSemaphoreTake(binSemaphore,portMAX_DELAY);//waiting for semaphore flag 
    res=xQueueReceive(I2C_event_handle,&queue_receive_buffer,portMAX_DELAY);
    if(res==pdTRUE){
    ESP_LOGI(TAG,"item received to queue");
    ESP_LOGI(TAG,"uint16_t data: %d",queue_receive_buffer[0]);
    }
    else{ESP_LOGI(TAG,"no item was received to queue");}
    }

      /*
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    ESP_LOGI(TAG1, "ESP WIFI initialization begin);
    wifi_init_sta();
    */

}


void app_main(void)
{
binSemaphore = xSemaphoreCreateBinary();
xTaskCreate(&i2c_slave_init,"I2C slave task",2048,NULL,1,NULL);
xTaskCreate(&wifi_ir_http_app,"WIFI & HTTP application",2048,NULL,1,NULL);

}

