/**
 * @file display.hpp
 * @author Siwat Sirichai (siwat@siwatinc.com)
 * @brief Class for interfacing with the CU Demonstration Secondary School IoT 2024 Display HMIs
 * @version 0.1
 * @date 2024-03-19
 *
 * @copyright Copyright (c) SIWAT SYSTEM 2024
 *
 */
#pragma once
#include <InternalDisplay.hpp>
#include <lcd_elements.hpp>
#include <ClimateCard.hpp>
#include <DigitalInputCard.hpp>
#include <DigitalOutputCard.hpp>
#include <RemoteVariable.hpp>
#include <SmartVariable.hpp>
#include <FRAM.h>
#include <ESPMegaIoT.hpp>
#include "config.hpp"

struct cud_display_conf_t
{
    RemoteVariable *aqi;
    HardwareSerial *uart;
    const int tx;
    const int rx;
    const uint32_t communication_baudrate;
    const uint32_t ota_baudrate;
    uint8_t light_pins[4];
    uint8_t fan_pins[3];
    uint8_t air_purifier_pin;
    uint8_t mosquito_zapper_pin;
    uint8_t socket_contactor_pin;
};

struct cud_display_cards_t
{
    DigitalInputCard *inputCard;
    DigitalOutputCard *outputCard;
    ClimateCard *ac;
    FRAM *fram;
    ESPMegaIoT *iot;
};

struct cud_display_light_group_t
{
    uint8_t element_id[4];
    const char *element_name[20];
    uint8_t picture_on[4];
    uint8_t picture_on_pressed[4];
    uint8_t picture_off[4];
    uint8_t picture_off_pressed[4];
};

struct cud_display_fan_group_t
{
    uint8_t element_id[3];
    const char *element_name[20];
    uint8_t picture_on[3];
    uint8_t picture_on_pressed[3];
    uint8_t picture_off[3];
    uint8_t picture_off_pressed[3];
};

class CUDDisplay : public ESPMegaDisplay
{
public:
    CUDDisplay(cud_display_conf_t *conf);
    ~CUDDisplay();
    void begin(cud_display_cards_t cards);
    void display_init();
    void set_ac_lock(bool state);
    bool get_ac_lock();
    void loop();
private:
    // States Calculation
    bool get_lights_state();
    bool get_fans_state();
    // Callbacks
    void handle_input_change(uint8_t pin, bool state);
    void handle_output_change(uint8_t pin, bool state);
    void handle_aqi_change(char *value);
    void handle_payload(uint8_t type, uint8_t *payload, uint8_t length);
    void handle_ac_change(uint8_t mode, uint8_t fan_speed, uint8_t temperature);
    void handle_ac_sensor(float temperature, float humidity);
    void handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch_type);
    void handle_lock_change(char* value);
    void handle_bound_change(char* value);
    void handle_mqtt_connected();
    // Change Display Elements
    void set_display_light_state(uint8_t row, bool state);
    void set_display_light_all_state();
    void set_display_fan_state(uint8_t row, bool state);
    void set_display_fan_all_state();
    void set_display_mosquito_zapper_state(bool state);
    void set_display_air_purifier_state(bool state);
    void refresh_display();
    void refresh_display_ac();
    void refresh_display_allsystem();
    void refresh_display_socket();
    // Helper Functions
    bool get_system_state();
    void system_toggle();
    // AC Functions and Variables
    uint8_t previous_mode; // Used to store mode prior to turning off
    uint32_t last_ac_button_press;
    uint8_t pending_temperature;
    bool ac_button_press_pending;
    bool standalone;
    uint8_t get_ac_temp_lower_bound();
    uint8_t get_ac_temp_upper_bound();
    // Local Variables
    cud_display_conf_t *conf;
    cud_display_cards_t cards;
    cud_display_light_group_t light_group;
    cud_display_fan_group_t fan_group;
    SmartVariable ac_lock;
    SmartVariable ac_temp_lower_bound;
    SmartVariable ac_temp_upper_bound;
    char *ac_lock_topic;
    char *ac_lock_set_topic;
    char *ac_lock_request_topic;
    char *ac_temp_lower_bound_topic;
    char *ac_temp_lower_bound_set_topic;
    char *ac_temp_lower_bound_request_topic;
    char *ac_temp_upper_bound_topic;
    char *ac_temp_upper_bound_set_topic;
    char *ac_temp_upper_bound_request_topic;
};