#include "display.hpp"

CUDDisplay::CUDDisplay(cud_display_conf_t *conf) : ESPMegaDisplay(conf->uart, conf->communication_baudrate, conf->ota_baudrate, conf->tx, conf->rx)
{
    this->conf = conf;
    // Initialize Light Group and Fan Group
    this->light_group = {
        .element_id = {LCD_DASHBOARD_ELEMENT_LIGHT_1, LCD_DASHBOARD_ELEMENT_LIGHT_2, LCD_DASHBOARD_ELEMENT_LIGHT_3, LCD_DASHBOARD_ELEMENT_LIGHT_4},
        .element_name = {LCD_DASHBOARD_ELEMENT_NAME_LIGHT_1, LCD_DASHBOARD_ELEMENT_NAME_LIGHT_2, LCD_DASHBOARD_ELEMENT_NAME_LIGHT_3, LCD_DASHBOARD_ELEMENT_NAME_LIGHT_4},
        .picture_on = {LCD_DASHBOARD_PIC_LIGHT_1_ON, LCD_DASHBOARD_PIC_LIGHT_2_ON, LCD_DASHBOARD_PIC_LIGHT_3_ON, LCD_DASHBOARD_PIC_LIGHT_4_ON},
        .picture_on_pressed = {LCD_DASHBOARD_PIC_LIGHT_1_ON_PRESSED, LCD_DASHBOARD_PIC_LIGHT_2_ON_PRESSED, LCD_DASHBOARD_PIC_LIGHT_3_ON_PRESSED, LCD_DASHBOARD_PIC_LIGHT_4_ON_PRESSED},
        .picture_off = {LCD_DASHBOARD_PIC_LIGHT_1_OFF, LCD_DASHBOARD_PIC_LIGHT_2_OFF, LCD_DASHBOARD_PIC_LIGHT_3_OFF, LCD_DASHBOARD_PIC_LIGHT_4_OFF},
        .picture_off_pressed = {LCD_DASHBOARD_PIC_LIGHT_1_OFF_PRESSED, LCD_DASHBOARD_PIC_LIGHT_2_OFF_PRESSED, LCD_DASHBOARD_PIC_LIGHT_3_OFF_PRESSED, LCD_DASHBOARD_PIC_LIGHT_4_OFF_PRESSED}};
    this->fan_group = {
        .element_id = {LCD_DASHBOARD_ELEMENT_FAN_1, LCD_DASHBOARD_ELEMENT_FAN_2, LCD_DASHBOARD_ELEMENT_FAN_3},
        .element_name = {LCD_DASHBOARD_ELEMENT_NAME_FAN_1, LCD_DASHBOARD_ELEMENT_NAME_FAN_2, LCD_DASHBOARD_ELEMENT_NAME_FAN_3},
        .picture_on = {LCD_DASHBOARD_PIC_FAN_1_ON, LCD_DASHBOARD_PIC_FAN_2_ON, LCD_DASHBOARD_PIC_FAN_3_ON},
        .picture_on_pressed = {LCD_DASHBOARD_PIC_FAN_1_ON_PRESSED, LCD_DASHBOARD_PIC_FAN_2_ON_PRESSED, LCD_DASHBOARD_PIC_FAN_3_ON_PRESSED},
        .picture_off = {LCD_DASHBOARD_PIC_FAN_1_OFF, LCD_DASHBOARD_PIC_FAN_2_OFF, LCD_DASHBOARD_PIC_FAN_3_OFF},
        .picture_off_pressed = {LCD_DASHBOARD_PIC_FAN_1_OFF_PRESSED, LCD_DASHBOARD_PIC_FAN_2_OFF_PRESSED, LCD_DASHBOARD_PIC_FAN_3_OFF_PRESSED}};
}

void CUDDisplay::begin()
{
    // Register callbacks
    auto binded_input_callback = std::bind(&CUDDisplay::handle_input_change, this, std::placeholders::_1, std::placeholders::_2);
    auto binded_output_callback = std::bind(&CUDDisplay::handle_output_change, this, std::placeholders::_1, std::placeholders::_2);
    auto binded_aqi_callback = std::bind(&CUDDisplay::handle_aqi_change, this, std::placeholders::_1);
    auto binded_payload_callback = std::bind(&CUDDisplay::handle_payload, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    auto binded_touch_callback = std::bind(&CUDDisplay::handle_touch, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    auto binded_ac_callback = std::bind(&CUDDisplay::handle_ac_change, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    auto binded_ac_sensor_callback = std::bind(&CUDDisplay::handle_ac_sensor, this, std::placeholders::_1, std::placeholders::_2);
    this->conf->inputCard->registerCallback(binded_input_callback);
    this->conf->outputCard->registerChangeCallback(binded_output_callback);
    this->conf->aqi->registerCallback(binded_aqi_callback);
    this->registerPayloadCallback(binded_payload_callback);
    this->registerTouchCallback(binded_touch_callback);
    this->conf->ac->registerChangeCallback(binded_ac_callback);
    this->conf->ac->registerSensorCallback(binded_ac_sensor_callback);
    // Initialize the display
    this->display_init();
}

void CUDDisplay::display_init()
{
    // Perform a reset on the display
    this->reset();
    // Set the display to the main screen
    this->jumpToPage(LCD_PAGE_ID_DASHBOARD);
    // Send the initial states to the display
    this->refresh_display();
}

bool CUDDisplay::get_lights_state()
{
    for (int i = 0; i < 4; i++)
    {
        if (this->conf->outputCard->getState(this->conf->light_pins[i]))
            return true;
    }
    return false;
}

bool CUDDisplay::get_fans_state()
{
    for (int i = 0; i < 3; i++)
    {
        if (this->conf->outputCard->getState(this->conf->fan_pins[i]))
            return true;
    }
    return false;
}

void CUDDisplay::handle_input_change(uint8_t pin, bool state)
{
    // This is not needed for now. We are only handling outputs
    // Putting this here in case we need to handle inputs in the future
}

void CUDDisplay::handle_output_change(uint8_t pin, bool state)
{
    // Check if it is a light or fan
    // If it's a light, call set_display_light_state
    // If it's a fan, call set_display_fan_state
    // If it's the air purifier, call set_display_air_purifier_state
    // If it's the mosquito zapper, call set_display_mosquito_zapper_state

    // Check if it's the air purifier
    if (pin == this->conf->air_purifier_pin)
    {
        this->set_display_air_purifier_state(state);
        return;
    }

    // Check if it's the mosquito zapper
    if (pin == this->conf->mosquito_zapper_pin)
    {
        this->set_display_mosquito_zapper_state(state);
        return;
    }

    // Loop through each to check if the pin is a light
    for (int i = 0; i < 4; i++)
    {
        if (pin == this->conf->light_pins[i])
        {
            this->set_display_light_state(i, state);
            this->set_display_light_all_state();
            return;
        }
    }
    // Loop through each to check if the pin is a fan
    for (int i = 0; i < 3; i++)
    {
        if (pin == this->conf->fan_pins[i])
        {
            this->set_display_fan_state(i, state);
            this->set_display_fan_all_state();
            return;
        }
    }
    // The pin is not the one that our display is handling, so we can ignore it
}

void CUDDisplay::handle_touch(uint8_t page_id, uint8_t element_id, uint8_t touch_type)
{
    // Check if element_id is the light all button
    if (element_id == LCD_DASHBOARD_ELEMENT_LIGHT_ALL)
    {
        // If it is, toggle all the lights
        bool light_on = this->get_lights_state();
        for (int i = 0; i < 4; i++)
        {
            this->conf->outputCard->setState(this->conf->light_pins[i], !light_on);
        }
        return;
    }
    // Check if element_id is the fan all button
    else if (element_id == LCD_DASHBOARD_ELEMENT_FAN_ALL)
    {
        // If it is, toggle all the fans
        bool fan_on = this->get_fans_state();
        for (int i = 0; i < 3; i++)
        {
            this->conf->outputCard->setState(this->conf->fan_pins[i], !fan_on);
        }
        return;
    }
    // Check if element_id is the air purifier button
    else if (element_id == LCD_DASHBOARD_ELEMENT_AIR_PURIFIER)
    {
        // If it is, toggle the air purifier
        this->conf->outputCard->setState(this->conf->air_purifier_pin, !this->conf->outputCard->getState(this->conf->air_purifier_pin));
        return;
    }
    // Check if element_id is the mosquito zapper button
    else if (element_id == LCD_DASHBOARD_ELEMENT_MOSQUITO_ZAPPER)
    {
        // If it is, toggle the mosquito zapper
        this->conf->outputCard->setState(this->conf->mosquito_zapper_pin, !this->conf->outputCard->getState(this->conf->mosquito_zapper_pin));
        return;
    }
    // Check if element_id is a light button
    for (int i = 0; i < 4; i++)
    {
        if (element_id == this->light_group.element_id[i])
        {
            // If it is, toggle the light
            this->conf->outputCard->setState(this->conf->light_pins[i], !this->conf->outputCard->getState(this->conf->light_pins[i]));
            return;
        }
    }
    // Check if element_id is a fan button
    for (int i = 0; i < 3; i++)
    {
        if (element_id == this->fan_group.element_id[i])
        {
            // If it is, toggle the fan
            this->conf->outputCard->setState(this->conf->fan_pins[i], !this->conf->outputCard->getState(this->conf->fan_pins[i]));
            return;
        }
    }
    // Check if element_id is the AC state button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_STATE)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Toggle the AC
        // Is the AC on?
        if (this->conf->ac->getMode() != 0)
        {
            // If it is, turn it off
            this->conf->ac->setMode(0);
        }
        else
        {
            // If it is not, turn it on
            this->conf->ac->setMode(previous_mode);
        }
        return;
    }
    // Check if element_id is the AC mode fan button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_MODE_FAN)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Set the AC mode to fan
        this->conf->ac->setMode(1);
        return;
    }
    // Check if element_id is the AC mode cool button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_MODE_COOL)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Set the AC mode to cool
        this->conf->ac->setMode(2);
        return;
    }
    // Check if element_id is the AC fan speed auto button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_AUTO)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Set the AC fan speed to auto
        this->conf->ac->setFanSpeed(0);
        return;
    }
    // Check if element_id is the AC fan speed low button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_LOW)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Set the AC fan speed to low
        this->conf->ac->setFanSpeed(1);
        return;
    }
    // Check if element_id is the AC fan speed medium button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_MEDIUM)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Set the AC fan speed to medium
        this->conf->ac->setFanSpeed(2);
        return;
    }
    // Check if element_id is the AC fan speed high button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_FAN_SPEED_HIGH)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Set the AC fan speed to high
        this->conf->ac->setFanSpeed(3);
        return;
    }
    // Check if element_id is the AC temperature up button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_TEMP_UP_BUTTON)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Increase the AC temperature
        this->conf->ac->setTemperature(this->conf->ac->getTemperature() + 1);
        return;
    }
    // Check if element_id is the AC temperature down button
    if (element_id == LCD_DASHBOARD_ELEMENT_AC_TEMP_DOWN_BUTTON)
    {
        // Is the control locked? If it is, we can ignore the touch
        if (this->ac_locked)
            return;
        // Decrease the AC temperature
        this->conf->ac->setTemperature(this->conf->ac->getTemperature() - 1);
        return;
    }
    // The element_id is not the one that our display is handling, so we can ignore it
}

void CUDDisplay::handle_aqi_change(char *value)
{
    // Update the AQI value on the display
    float aqi = atof(value);
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.txt=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, (int)aqi);
    this->sendStopBytes();
    // Update the AQI picture on the display
    if (aqi <= 50)
    {
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_GOOD);
        this->sendStopBytes();
    }
    else if (aqi <= 100)
    {
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_MODERATE);
        this->sendStopBytes();
    }
    else if (aqi <= 150)
    {
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_UNHEALTHY_FOR_SENSITIVE_GROUPS);
        this->sendStopBytes();
    }
    else if (aqi <= 200)
    {
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_UNHEALTHY);
        this->sendStopBytes();
    }
    else if (aqi <= 300)
    {
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_VERY_UNHEALTHY);
        this->sendStopBytes();
    }
    else
    {
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AQI_TEXT, LCD_DASHBOARD_PIC_AQI_HAZARDOUS);
        this->sendStopBytes();
    }
    this->giveSerialMutex();
}

/**
 * @brief Handle the payload from the display that is not handled by the parent class
 *
 * @param type Payload type
 * @param payload The payload itself
 * @param length The length of the payload excluding the type
 */
void CUDDisplay::handle_payload(uint8_t type, uint8_t *payload, uint8_t length)
{
    // If payload of type 0x92 is received
    // Reset the display and reinitialize it
    if (type == 0x92)
    {
        this->display_init();
    }
}

void CUDDisplay::handle_ac_change(uint8_t mode, uint8_t fan_speed, uint8_t temperature)
{
    // Set the previous mode to the current mode if the current mode is not 0
    if (mode != 0)
    {
        previous_mode = mode;
    }
    this->refresh_display_ac();
}

void CUDDisplay::set_display_light_state(uint8_t row, bool state)
{
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", this->light_group.element_name[row], state ? this->light_group.picture_on[row] : this->light_group.picture_off[row]);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", this->light_group.element_name[row], state ? this->light_group.picture_on_pressed[row] : this->light_group.picture_off_pressed[row]);
    this->sendStopBytes();
    this->giveSerialMutex();
}

void CUDDisplay::set_display_light_all_state()
{
    bool light_on = this->get_lights_state();
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_LIGHT_ALL, light_on ? LCD_DASHBOARD_PIC_LIGHT_ALL_ON : LCD_DASHBOARD_PIC_LIGHT_ALL_OFF);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_LIGHT_ALL, light_on ? LCD_DASHBOARD_PIC_LIGHT_ALL_ON_PRESSED : LCD_DASHBOARD_PIC_LIGHT_ALL_OFF_PRESSED);
    this->sendStopBytes();
    this->giveSerialMutex();
}

void CUDDisplay::set_display_fan_state(uint8_t row, bool state)
{
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", this->fan_group.element_name[row], state ? this->fan_group.picture_on[row] : this->fan_group.picture_off[row]);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", this->fan_group.element_name[row], state ? this->fan_group.picture_on_pressed[row] : this->fan_group.picture_off_pressed[row]);
    this->sendStopBytes();
    this->giveSerialMutex();
}

void CUDDisplay::set_display_fan_all_state()
{
    bool fan_on = this->get_fans_state();
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_FAN_ALL, fan_on ? LCD_DASHBOARD_PIC_FAN_ALL_ON : LCD_DASHBOARD_PIC_FAN_ALL_OFF);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_FAN_ALL, fan_on ? LCD_DASHBOARD_PIC_FAN_ALL_ON_PRESSED : LCD_DASHBOARD_PIC_FAN_ALL_OFF_PRESSED);
    this->sendStopBytes();
    this->giveSerialMutex();
}

void CUDDisplay::set_display_mosquito_zapper_state(bool state)
{
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_MOSQUITO_ZAPPER, state ? LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_ON : LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_OFF);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_MOSQUITO_ZAPPER, state ? LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_ON_PRESSED : LCD_DASHBOARD_PIC_MOSQUITO_ZAPPER_OFF_PRESSED);
    this->sendStopBytes();
    this->giveSerialMutex();
}

void CUDDisplay::set_display_air_purifier_state(bool state)
{
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AIR_PURIFIER, state ? LCD_DASHBOARD_PIC_AIR_PURIFIER_ON : LCD_DASHBOARD_PIC_AIR_PURIFIER_OFF);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AIR_PURIFIER, state ? LCD_DASHBOARD_PIC_AIR_PURIFIER_ON_PRESSED : LCD_DASHBOARD_PIC_AIR_PURIFIER_OFF_PRESSED);
    this->sendStopBytes();
    this->giveSerialMutex();
}

void CUDDisplay::refresh_display()
{
    // Send every states to the display
    this->set_display_light_all_state();
    this->set_display_fan_all_state();
    this->set_display_air_purifier_state(this->conf->outputCard->getState(this->conf->air_purifier_pin));
    this->set_display_mosquito_zapper_state(this->conf->outputCard->getState(this->conf->mosquito_zapper_pin));
    for (int i = 0; i < 4; i++)
    {
        this->set_display_light_state(i, this->conf->outputCard->getState(this->conf->light_pins[i]));
    }
    for (int i = 0; i < 3; i++)
    {
        this->set_display_fan_state(i, this->conf->outputCard->getState(this->conf->fan_pins[i]));
    }
}

void CUDDisplay::refresh_display_ac()
{
    // Fetch data from the AC
    uint8_t mode = this->conf->ac->getMode();
    bool state = mode != 0;
    previous_mode = previous_mode == 0 ? 2 : previous_mode;
    bool drawn_mode = mode == 0? previous_mode : mode;
    uint8_t fan_speed = this->conf->ac->getFanSpeed();
    uint8_t temperature = this->conf->ac->getTemperature();
    // Draw the state picture set
    // Is the AC locked?
    if (this->ac_locked)
    {
        // When the display is locked
        // the state picture set we use is the locked state picture set
        this->takeSerialMutex();
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON_LOCKED : LCD_DASHBOARD_PIC_AC_STATE_OFF_LOCKED);
        this->sendStopBytes();
        // Since the display is locked, when pressed, the state picture set should not change
        this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON_LOCKED : LCD_DASHBOARD_PIC_AC_STATE_OFF_LOCKED);
        this->sendStopBytes();
        // Set Alpha of Locked Icon to 127
        this->displayAdapter->printf("%s.aph=%d", LCD_DASHBOARD_ELEMENT_NAME_ICO_LOCK, 127);
        this->sendStopBytes();
        this->giveSerialMutex();
    }
    else
    {
        // When the display is not locked
        // the state picture set we use is the unlocked state picture set
        this->takeSerialMutex();
        this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON : LCD_DASHBOARD_PIC_AC_STATE_OFF);
        this->sendStopBytes();
        // When pressed, the state picture set should change
        this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_STATE, state ? LCD_DASHBOARD_PIC_AC_STATE_ON_PRESSED : LCD_DASHBOARD_PIC_AC_STATE_OFF_PRESSED);
        this->sendStopBytes();
        // Set Alpha of Locked Icon to 0
        this->displayAdapter->printf("%s.aph=%d", LCD_DASHBOARD_ELEMENT_NAME_ICO_LOCK, 0);
        this->sendStopBytes();
        this->giveSerialMutex();
    }
    // Draw the mode picture set
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_COOL, drawn_mode == 2 ? LCD_DASHBOARD_PIC_AC_MODE_COOL_ACTIVE : LCD_DASHBOARD_PIC_AC_MODE_COOL_INACTIVE);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_COOL, drawn_mode == 2 ? LCD_DASHBOARD_PIC_AC_MODE_COOL_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_MODE_COOL_INACTIVE_PRESS);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_FAN, drawn_mode == 1 ? LCD_DASHBOARD_PIC_AC_MODE_FAN_ACTIVE : LCD_DASHBOARD_PIC_AC_MODE_FAN_INACTIVE);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_MODE_FAN, drawn_mode == 1 ? LCD_DASHBOARD_PIC_AC_MODE_FAN_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_MODE_FAN_INACTIVE_PRESS);
    this->sendStopBytes();
    this->giveSerialMutex();
    // Draw the fan speed picture set
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_AUTO, fan_speed == 0 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_INACTIVE);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_AUTO, fan_speed == 0 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_AUTO_INACTIVE_PRESS);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_LOW, fan_speed == 1 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_INACTIVE);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_LOW, fan_speed == 1 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_LOW_INACTIVE_PRESS);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_MEDIUM, fan_speed == 2 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_INACTIVE);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_MEDIUM, fan_speed == 2 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_MEDIUM_INACTIVE_PRESS);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_HIGH, fan_speed == 3 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_ACTIVE : LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_INACTIVE);
    this->sendStopBytes();
    this->displayAdapter->printf("%s.pic2=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_FAN_SPEED_HIGH, fan_speed == 3 ? LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_ACTIVE_PRESS : LCD_DASHBOARD_PIC_AC_FAN_SPEED_HIGH_INACTIVE_PRESS);
    this->sendStopBytes();
    this->giveSerialMutex();
    // Draw the temperature
    this->takeSerialMutex();
    this->displayAdapter->printf("%s.txt=%d", LCD_DASHBOARD_ELEMENT_NAME_AC_TEMPERATURE, temperature);
    this->sendStopBytes();
    this->giveSerialMutex();
    
}

void CUDDisplay::system_toggle()
{
    // TODO: Implement this
}


void CUDDisplay::set_ac_lock(bool state)
{
    this->ac_locked = state;
    this->refresh_display_ac();
}

bool CUDDisplay::get_ac_lock()
{
    return this->ac_locked;
}