// © Copyright CERN, Riga Technical University and University of Liverpool 2020.
// All rights not expressly granted are reserved. 
// 
// This file is part of hev-sw.
// 
// hev-sw is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public Licence as published by the Free
// Software Foundation, either version 3 of the Licence, or (at your option)
// any later version.
// 
// hev-sw is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licence
// for more details.
// 
// You should have received a copy of the GNU General Public License along
// with hev-sw. If not, see <http://www.gnu.org/licenses/>.
// 
// The authors would like to acknowledge the much appreciated support
// of all those involved with the High Energy Ventilator project
// (https://hev.web.cern.ch/).


#ifndef ALARM_LOOP_H
#define ALARM_LOOP_H

#include <Arduino.h>
#include "common.h"
#include "CommsFormat.h"
#include "AudioVisualController.h"
//#include "Adafruit_TPA2016.h"

class BreathingLoop;
class AlarmLoop {

public:
    AlarmLoop(BreathingLoop *bl);  //, Adafruit_TPA2016* TPA2016);
    ~AlarmLoop();

    void fireAlarms();
    void updateValues(readings fast_data, cycle_readings cr);

    void muteAlarm(bool mute);
    bool isAlarmMuted();
    int32_t getAlarmMuteTimeRemaining();

    void setVolume(ALARM_VOLUME_LEVEL);
    void getVolume();

    void resetAlarms();

       float getValue               (ALARM_CODES alarm_code) { return _alarms.values[alarm_code];                  }
       float getThresholdMin        (ALARM_CODES alarm_code) { return _alarms.thresholds_min[alarm_code];          }
       float getThresholdMax        (ALARM_CODES alarm_code) { return _alarms.thresholds_max[alarm_code];          }
       float getThresholdAbsoluteMin(ALARM_CODES alarm_code) { return _alarms.thresholds_absolute_min[alarm_code]; }
       float getThresholdAbsoluteMax(ALARM_CODES alarm_code) { return _alarms.thresholds_absolute_max[alarm_code]; }
    uint32_t getLastBeginTrigger    (ALARM_CODES alarm_code) { return _alarms.last_begin_trigger[alarm_code];      }
    uint32_t getLastEndTrigger      (ALARM_CODES alarm_code) { return _alarms.last_end_trigger[alarm_code];        }
    uint32_t getLastBroadcast       (ALARM_CODES alarm_code) { return _alarms.last_broadcasts[alarm_code];         }

    void setAlarmValue(ALARM_CODES alarm_code, float value) { _alarms.values[alarm_code] = value; }
    bool setAlarmThresholdMin(ALARM_CODES alarm_code, float threshold_min);
    bool setAlarmThresholdMax(ALARM_CODES alarm_code, float threshold_max);
    void setLastBroadcast(ALARM_CODES alarm_code, uint32_t last_broadcast) { _alarms.last_broadcasts[alarm_code] = last_broadcast; }

    ALARM_TYPE getHighestPriority() { return _type; }
    ALARM_TYPE getPriority(ALARM_CODES alarm_code) { return _alarms.priorities[alarm_code]; }
    bool       isActive(ALARM_CODES alarm_code) { return _alarms.actives[alarm_code]; }
    void setBatteryAlarms(battery_data_format &bat);

private:
    ALARM_TYPE checkThresholds();
    void setBatteryThresholds();

    bool shouldPatientPressureAlarmTrigger(bool alarm_was_active);
    void handlePatientPressureAlarmActive(bool alarm_was_active);

private:
    BreathingLoop *_breathing_loop;

    AudioVisualController _av_controller;

    ALARM_TYPE _type = ALARM_TYPE::ALARM_TYPE_UNKNOWN;
    alarms _alarms;

    bool     _mute_alarm;
    uint32_t _last_mute_command;

    uint32_t _last_alarm_reset;

    ALARM_VOLUME_LEVEL _alarm_volume;
};

#endif
