#include <Arduino.h>
#include "Settings.h"
#include "pumppwm.h"

/**
 * @brief Установить режим питания.
 * @param Mode Режим (строка)
 */
void set_power_mode(String Mode);

/**
 * @brief Установить текущую мощность.
 * @param power Мощность (Вт)
 */
void set_current_power(float power);

/**
 * @brief Включить или выключить буззер.
 * @param On true — включить, false — выключить
 */
void set_buzzer(bool On);

/**
 * @brief Сбросить счетчик датчиков.
 */
void reset_sensor_counter();

/**
 * @brief Проверить ошибки питания и обработать их.
 */
void check_power_error();

/**
 * @brief Включить или выключить питание.
 * @param On true — включить, false — выключить
 */
void set_power(bool On);

/**
 * @brief Создать файл с данными текущей сессии.
 */
void create_data();

/**
 * @brief Открыть или закрыть клапан.
 * @param Val true — открыть, false — закрыть
 * @param msg true — отправить сообщение
 */
void open_valve(bool Val, bool msg);

/**
 * @brief Установить ШИМ для насоса.
 * @param duty Значение ШИМ
 */
void set_pump_pwm(float duty);

/**
 * @brief Установить скорость насоса по ПИД-регулированию.
 * @param temp Целевая температура
 */
void set_pump_speed_pid(float temp);

/**
 * @brief Отправить сообщение пользователю.
 * @param m Текст сообщения
 * @param msg_type Тип сообщения
 */
void SendMsg(const String& m, MESSAGE_TYPE msg_type);

/**
 * @brief Проверить, идет ли кипячение.
 * @return true если кипит, иначе false
 */
bool check_boiling();

/**
 * @brief Установить температуру воды (ШИМ).
 * @param duty Значение ШИМ
 */
void stop_process(String reason);

void WaterSratusCheck();
void WaterTempAlarmPowerReg();
void CheckTWatherPumpOFF(); // Отключение насоса по снижению Т воды

void set_water_temp(float duty) {
  if (SamSetup.UseWP) {
    bk_pwm = duty;
    if (pump_started) {
      pump_pwm.write(bk_pwm);
      water_pump_speed = bk_pwm;
    }
  } else
    SendMsg(("Управление насосом не поддерживается вашим оборудованием"), NOTIFY_MSG);
  }

/**
 * @brief Основной цикл работы бражной колонны. Запускает нагрев, проверяет условия завершения.
 */
void bk_proc() {
  if (!PowerOn) {
    if (SamSetup.UseMQTT) {
        SessionDescription.replace(",", ";");
        MqttSendMsg((String)chipId + "," + SamSetup.TimeZone + "," + SAMOVAR_VERSION + ",BK," + SessionDescription, "st");
    }
    set_power(true);
    if (SamSetup.PwrType != NO_POVER_REG) {
      delay(1000);
      set_power_mode(POWER_SPEED_MODE); //а здесь опять разгон через секунду
    } else {
      current_power_mode = POWER_SPEED_MODE;
      digitalWrite(RELE_CHANNEL4, SamSetup.rele4);
    }
    create_data();  //создаем файл с данными
    SteamSensor.Start_Pressure = bme_pressure;
    SendMsg(("Включен нагрев бражной колонны"), NOTIFY_MSG);
    }

  if (TankSensor.avgTemp >= SamSetup.DistTemp) {
    stop_process("Работа бражной колонны завершена");
  }
  vTaskDelay(10 / portTICK_PERIOD_MS);
}

/**
 * @brief Проверка и обработка аварийных ситуаций в работе бражной колонны.
 */
void check_alarm_bk() {

  if (PowerOn && !valve_status && TankSensor.avgTemp >= SamSetup.Opn_Vlv_Tnk_T) {
    open_valve(true, true);//Откройте воду!
    if (SamSetup.UseWP) {
        set_pump_pwm(bk_pwm);
    }
  }

  //Определяем, что началось кипение - вода охлаждения начала нагреваться
  //Если разгон и (кипит или темература пара или царги выше уставки)
  if (current_power_mode == POWER_SPEED_MODE 
      && (check_boiling() || SteamSensor.avgTemp > SamSetup.Ch_Pwr_Md_St_T 
      || PipeSensor.avgTemp > SamSetup.Ch_Pwr_Md_St_T)) {
    if (SamSetup.PwrType != NO_POVER_REG) {
      if (SamSetup.PwrType >= STAB_AVR)
        set_current_power(45);//Отключаем разгон и Выставляем что? почему? он же в цикле опять включится
      else
        set_current_power(200);        
    } else {
      current_power_mode = POWER_WORK_MODE;
      digitalWrite(RELE_CHANNEL4, !SamSetup.rele4);
    }
  }
  CheckTWatherPumpOFF(); // Отключение насоса по снижению Т воды

  //Проверяем, что температурные параметры не вышли за предельные значения
  if ((WaterSensor.avgTemp >= SamSetup.Max_Wt_T) && PowerOn) {
    set_buzzer(true);
    //Если с температурой проблемы - выключаем нагрев, пусть оператор разбирается
    set_power(false);
    SendMsg(("Аварийное отключение! Превышена максимальная температура воды охлаждения!"), ALARM_MSG);
  }

  WaterSratusCheck();
  WaterTempAlarmPowerReg();
  if (SamSetup.PwrType != NO_POVER_REG) {
    check_power_error();// проверяем стаб
  }
  vTaskDelay(10 / portTICK_PERIOD_MS);
}
void bk_finish() {
  stop_process("Работа бражной колонны завершена");
}