#include <inttypes.h>

#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "esp_err.h"
#include "esp_log.h"
#include "esp_mac.h"
#include "esp_lcd_panel_ops.h"
#include "driver/i2c_master.h"

#include "lvgl.h"

#include "common.h"
#include "usb.h"
#include "lcd.h"
#include "ui.h"

static const char *TAG = "valconomy";

char val_dev_serial[13];

i2c_master_bus_handle_t i2c_bus_handle;
i2c_master_dev_handle_t exio_cfg_handle, exio_o_handle;

static void val_i2c_master_init(void) {
  ESP_LOGI(TAG, "Init I2C");
  i2c_master_bus_config_t i2c_mst_config = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = I2C_NUM_0,
    .scl_io_num = 9,
    .sda_io_num = 8,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = true,
  };

  ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &i2c_bus_handle));

  i2c_device_config_t exio_dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x24, // CH422G config register
    .scl_speed_hz = SCL_SPEED,
  };

  ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &exio_dev_cfg, &exio_cfg_handle));
  exio_dev_cfg.device_address = 0x38;
  ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_handle, &exio_dev_cfg, &exio_o_handle));
}

void app_main(void) {
  // Use MAC address for serial number
  uint8_t mac[6] = { 0 };
  ESP_ERROR_CHECK(esp_read_mac(mac, ESP_MAC_EFUSE_FACTORY));
  snprintf(
    val_dev_serial, sizeof(val_dev_serial),
    "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  val_i2c_master_init();

  val_usb_init();

  esp_lcd_panel_handle_t lcd_panel = val_setup_lcd();
  assert(lcd_panel);
  esp_lcd_touch_handle_t touch_panel = val_setup_touch();
  assert(touch_panel);

  lv_display_t *display = val_setup_lvgl(lcd_panel, touch_panel);
  assert(display);

  ESP_LOGI(TAG, "Display LVGL UI");
  // Lock the mutex due to the LVGL APIs are not thread-safe
  assert(val_lvgl_lock(-1));
  val_lvgl_ui(display);
  val_lvgl_unlock();
}