#include <stdio.h>
#include <math.h>
#include "esp_log.h"
#include "spi_bus.h"
#include "screen_driver.h"
#include "lvgl_gui.h"
#include "common.h"
#include "compass_pointer.h"
#include "compass_reading.h"
#include "display.h"
#include "main_menu.h"
static const char *TAG = "DISPLAY";
static const size_t queue_len = 10;
static scr_driver_t g_lcd;
static scr_info_t g_lcd_info;
static QueueHandle_t queue;
static float theta = 0;
static FP_MENU_PANEL current_menu_panel;
static void init_screen() {
	esp_err_t ret = ESP_OK;
	spi_config_t bus_conf = { .miso_io_num = SPI2_MISO,
			.mosi_io_num = SPI2_MOSI, .sclk_io_num = SPI2_SCK,
			.max_transfer_sz = 2 * 240 * 240 + 10, };
	spi_bus_handle_t s_spi2_bus_handle = spi_bus_create(SPI2_HOST, &bus_conf);
	scr_interface_spi_config_t spi_lcd_cfg = { .spi_bus = s_spi2_bus_handle,
			.pin_num_cs = LCD_SPI_CS_PIN, .pin_num_dc = LCD_SPI_DC_PIN,
			.clk_freq = LCD_SPI_CLOCK_FREQ, .swap_data = true, };
	scr_interface_driver_t *iface_drv;
	scr_interface_create(SCREEN_IFACE_SPI, &spi_lcd_cfg, &iface_drv);
	ret = scr_find_driver(SCREEN_CONTROLLER_ST7789, &g_lcd);
	if (ESP_OK != ret) {
		ESP_LOGE(TAG, "screen find failed");
		return;
	}
	scr_controller_config_t lcd_cfg =
			{ .interface_drv = iface_drv, .pin_num_rst = LCD_SPI_RESET_PIN,
					.pin_num_bckl = LCD_SPI_BL_PIN, .rst_active_level = 0,
					.bckl_active_level = 1, .offset_hor = 0, .offset_ver = 0,
					.width = 240, .height = 240, .rotate = SCR_DIR_LRTB, };
	ret = g_lcd.init(&lcd_cfg);
	if (ESP_OK != ret) {
		ESP_LOGE(TAG, "screen initialize failed");
		return;
	}
	g_lcd.get_info(&g_lcd_info);
	ESP_LOGD(TAG, "Screen name:%s | width:%d | height:%d", g_lcd_info.name,
			g_lcd_info.width, g_lcd_info.height);
	lvgl_init(&g_lcd, NULL);
	lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN,
			LV_STATE_DEFAULT, LV_COLOR_BLACK);
}
void init_menu() {
	init_main_menu();
	current_menu_panel = main_menu_panel;
	current_menu_panel(SHOW_PANEL, MAINTAIN_ITEM);
	ESP_LOGI(TAG,"FN %p",current_menu_panel);
}
void init_display(QueueHandle_t *const ref_queue) {
	queue = xQueueCreate(queue_len, sizeof(DisplayMsg));
	*ref_queue = queue;
	init_screen();
	init_compass_panel();
	init_compass_reading_panel();
	init_menu();
}
static void process_compass_msg(const DisplayMsg *const msg) {
	theta = msg->theta;
	ESP_LOGD(TAG, "Theta arc:%f, degree:%f", msg->theta, msg->theta/M_PI*180);
	compass_update_theta(theta);
	compass_reading_panel_update_reading(msg->rx, msg->ry, msg->rz, msg->x,
			msg->y, msg->z, msg->theta);
}
static void process_menu_navigate_msg(DisplayMsg *msg) {
	ESP_LOGI(TAG,"PROCESS");
	current_menu_panel(msg->page_action, msg->item_action);
}
void display_task(void *args) {
	DisplayMsg msg;
	ESP_LOGI(TAG,"FN %p",current_menu_panel);
	while (1) {
		vTaskDelay(pdMS_TO_TICKS(500));
		ESP_LOGI(TAG,"FN %p",current_menu_panel);
		if (xQueueReceive(queue, &msg, 100) == pdTRUE) {
			if (msg.type == TYPE_COMPASS_READ)
				process_compass_msg(&msg);
			else if (msg.type == TYPE_MENU_NAVIGATE) {
				process_menu_navigate_msg(&msg);
			}
		}
	}
}
