/**
 * @brief Header file for the ESPMega IoT Core library.
 * 
 * This library provides functions for controlling various IoT modules such as climate, IR, and input/output.
 * It also includes functions for MQTT communication, LCD display, and OTA updates.
 * 
 * @note This library requires the ESPMegaPRO library to be installed.
 * 
 */
#pragma once

#include <ESPMegaPRO.h>
#include "user_code.hpp"
#ifdef ENABLE_CLIMATE_MODULE
#ifndef ENABLE_IR_MODULE
#error "The Climate Module Requires the IR Module to be enabled with #define ENABLE_IR_MODULE"
#endif
#endif
#include <ETH.h>
#include <PubSubClient.h>
#include <Thread.h>
#include <StaticThreadController.h>
#ifdef ENABLE_IR_MODULE
#include <IRremote.hpp>
#endif
#include <dhtnew.h>
#include <time.h>
#ifdef ENABLE_INTERNAL_LCD
#include <EasyNextionLibrary.h>
#endif
#include <WiFiClient.h>
#ifdef ENABLE_WEBUI
#include <WebServer.h>
#include <Update.h>
#endif
#include "espmega_iot_lcd.hpp"

#ifdef ENABLE_CLIMATE_MODULE
#include "ir_codes.hpp"
#endif
#ifdef ENABLE_WEBUI
#include "espmega_iot_ota.hpp"
#endif
#include "espmega_iot_timer.hpp"

void mqtt_callback(char* topic, byte* payload, unsigned int length);
void virtual_interrupt_loop();
void virtual_interrupt_callback(int pin, int state);
void virtual_interrupt_preload();
void network_begin();
void mqtt_connect();
void mqtt_subscribe();
void thread_initialization();
void pwm_state_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length);
void pwm_value_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length);
void state_request_callback();
void io_begin();
void ir_loop();

void ota_begin();

void publish_pwm_states();
void publish_pwm_state(int id);
void pwm_set_state(int id, int state);
void pwm_set_value(int id, int value);
void pwm_toggle(int id);
void pwm_toggle(int id1, int id2);
void pwm_cycle_value(int id);
bool pwm_get_state(int id);
uint16_t pwm_get_value(int id);
boolean pwm_group_state(int id1, int id2);
bool input_get_state(int id);

void publish_ac_state();
void publish_env_state();
uint8_t ac_get_temperature();
uint8_t ac_get_mode();
uint8_t ac_get_fan_speed();
void ac_state_callback(char* topic, uint8_t topic_length, char* payload, unsigned int payload_length);
void ac_set_state(int mode, int temperature, int fan_speed);

void publish_input_states();
void publish_input_state(int id);
void publish_input_state(int id, int state);

void lcd_begin();
void lcd_loop();
void lcd_refresh();
void lcd_refresh_pd();
void lcd_top_bar_update();
void trigger0();
void trigger1();
void trigger2();
void trigger3();
void trigger4();
void trigger5();
void trigger6();
void trigger7();
void trigger8();
void trigger9();
void trigger10();
void trigger11();
void trigger12();
void trigger13();
void trigger14();
void trigger15();

void fram_retrieve_init();
void fram_pwm_update();

void lcd_ac_refresh_fan();
void lcd_ac_refresh_mode();

void set_ip(String address);
void set_netmask(String address);
void set_dns(String address);
void set_gw(String address);
void set_mqtt_server(String address);
void fram_ip_update(uint16_t rom_address, uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4);
IPAddress fram_ip_retrieve(uint16_t rom_address);
void set_hostname(String hostname);
void fram_hostname_retrieve();
void set_basetopic(String topic);
void fram_basetopic_retrieve();
void mqtt_port_set(uint16_t port);
void fram_mqtt_port_retrieve();
void fram_mqtt_username_retrieve();
void fram_mqtt_password_retrieve();
void set_mqtt_username(String username);
void set_mqtt_password(String password);
void fram_mqtt_useauth_retrieve();
void set_mqtt_useauth(bool use_auth);

void factory_reset();
void check_boot_reset();

void enable_adc(int id);
void disable_adc(int id);
void adc_update(int id);
void adc_update_force(int id);
void adc_update_all();
void adc_loop();
void publish_adc_value(int id);
void publish_adc_values();
uint16_t get_adc_value(int id);
void adc_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length);
void dac_set_value(int id, int value);
void dac_set_state(int id, bool state);
void dac_set_value_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length);
void dac_set_state_callback(char *topic, uint8_t topic_length, char *payload, unsigned int payload_length);
void publish_dac_value(int id);
void publish_dac_state(int id);
void publish_dac_values();
void publish_dac_states();
void publish_adc_state(int id);
void publish_adc_states();
uint16_t adc_get_value(int id);
bool adc_get_state(int id);
uint16_t dac_get_value(int id);
bool dac_get_state(int id);