//
// Created by robtor on 10.01.23.
//

#include "RelayChannel.h"

namespace floatpump {
    namespace io {
        RelayChannel::RelayChannel(GPIO_TypeDef *gpio, uint16_t pin, bool inverted, RelayChannel::state initial)
                : m_gpio(gpio), m_gpio_pin(pin), m_inverted(inverted) {
            if (initial == state::ON)
                switchRelay(state::ON);
        }

        void RelayChannel::switchRelay(RelayChannel::state st) {

            if (st == state::ON && m_state == state::OFF && getRemainingCooldown() == 0) {
                //Check if cooldown expired and enable Relay if true
                HAL_GPIO_WritePin(m_gpio, m_gpio_pin, (m_inverted) ? GPIO_PIN_RESET : GPIO_PIN_SET);
                m_state = state::ON;
            } else if (st == state::OFF && m_state == state::ON) {
                //Store last tick value when turning off
                //Always offer turning off!
                m_lastTick = HAL_GetTick();
                HAL_GPIO_WritePin(m_gpio, m_gpio_pin, (m_inverted) ? GPIO_PIN_SET : GPIO_PIN_RESET);
                m_state = state::OFF;
            }
        }


        void RelayChannel::setCooldown(uint16_t ms) {
            m_cooldown = ms;
        }

        uint16_t RelayChannel::getRemainingCooldown() const {
            uint32_t elapsed = (HAL_GetTick() - m_lastTick);

            if (elapsed <= m_cooldown)
                return m_cooldown - (HAL_GetTick() - m_lastTick);
            else
                return 0;
        }

        void RelayChannel::setInverted(bool inv) {
            m_inverted = inv;
        }

        void RelayChannel::forceRefresh() {
            if ( m_state == state::ON) {
                HAL_GPIO_WritePin(m_gpio, m_gpio_pin, (m_inverted) ? GPIO_PIN_RESET : GPIO_PIN_SET);
            } else if (m_state == state::OFF) {
                HAL_GPIO_WritePin(m_gpio, m_gpio_pin, (m_inverted) ? GPIO_PIN_SET : GPIO_PIN_RESET);
            }
        }
    } // floatpump
} // io