/* HOW TO USE:
 *  
 *  Arm the alarm by flipping the Key-Switch to the down-position
 *  Trigger the alarm by pressing the "Tür-Kontaktschalter" when the Key-Switch is flipped
 *  When the alarm is active, the LED1 on the Relay should blink, indicating the state of the relay
 *  Deactivate the active alarm by toggling the Key-Switch to the up-position
 *  Or wait for the alarm to time out (currently after 30 seconds)
 *  After an alarm timeout, you have to re-arm the alarm by disarming and arming it again (flipping the Key-Switch up and down)
*/


// Define the pins
#define RELAY_PIN 16
//#define RELAY_PIN_2 17 // Not used 
#define KEY_SWITCH_PIN 22
#define DOOR_PIN 19
#define LED_PIN 23
#define SLEEP_BUTTON_PIN 18

// Suggested by RenzGPT
#define ALARM_IS_ARMED HIGH     // Alarm is armed when the Key-Circuit is closed
#define ALARM_IS_TRIGGERED LOW // Alarm is triggert when the Door-Circuit is closed

// Define the duration for which the relay should stay active (in milliseconds)
const uint32_t RELAY_TOGGLE_INTERVAL = 400; // 0.4 seconds
const uint32_t ALARM_MAX_ACTIVE_TIME = 10000; // 30 seconds (maybe increase to 5-10 Minutes)

// Variables to keep track of the state and timing
uint32_t alarm_activated_time = 0;
uint32_t relay_last_toggle_time = 0;
bool alarm_active = false;
bool relay_state = false;
bool alarm_timed_out = false;

// State machine states
enum AlarmState {
  ALARM_DEACTIVATED,
  ALARM_ARMED,
  ALARM_ACTIVE,
  ALARM_ACTIVE_COUNTDOWN,
  ALARM_TIMEOUT,
};

AlarmState current_state = ALARM_DEACTIVATED;

void setup() {
  Serial.begin(115200);
  Serial.println("Alarm-System is started!");

  // Initialize the pins
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  pinMode(KEY_SWITCH_PIN, INPUT_PULLUP);
  pinMode(DOOR_PIN, INPUT_PULLUP);
  pinMode(SLEEP_BUTTON_PIN, INPUT_PULLUP);

  // Make sure the relay is off initially
  digitalWrite(RELAY_PIN, LOW);
  digitalWrite(LED_PIN, HIGH);
}

void enter_ALARM_DEACTIVATED(){
  current_state = ALARM_DEACTIVATED;
  Serial.println("ALARM_DEACTIVATED");
}

void enter_ALARM_ARMED(){
  current_state = ALARM_ARMED;
  Serial.println("ALARM_ARMED");
}

void enter_ALARM_ACTIVE(){
  current_state = ALARM_ACTIVE;
  relay_state = true;
  relay_last_toggle_time = millis();
  Serial.println("ALARM_ACTIVE");
}

void enter_ALARM_ACTIVE_COUNTDOWN(){
  current_state = ALARM_ACTIVE_COUNTDOWN;
  alarm_activated_time = millis();
  Serial.println("ALARM_ACTIVE_COUNTDOWN");
}

void enter_ALARM_TIMEOUT(){
  current_state = ALARM_TIMEOUT;
  Serial.println("ALARM_TIMEOUT");
}




void loop() {
  // Read the state of the key switch and the door
  bool key_switch_state = digitalRead(KEY_SWITCH_PIN);
  bool door_state = digitalRead(DOOR_PIN);
  bool sleep_button_state = digitalRead(SLEEP_BUTTON_PIN);

  if(sleep_button_state == 0){
    digitalWrite(RELAY_PIN, HIGH);

  }else{

    // State machine handling
    switch (current_state) {
      case ALARM_DEACTIVATED:
        // Set variables for ALARM_DEACTIVATED state
        alarm_active = false;
        relay_state = false;
        alarm_timed_out = false;

        //  Switch to ALARM_ARMED state if the Key-Switch is activated
        if(key_switch_state == ALARM_IS_ARMED) 
          enter_ALARM_ARMED();
        break;

      case ALARM_ARMED:
        // Set variables for ALARM_ARMED state
        alarm_active = false;
        relay_state = false;
        alarm_timed_out = false;

        // Switch to ALARM_DEACTIVATED state if the Key-Switch is deactivated
        if(key_switch_state != ALARM_IS_ARMED) 
          enter_ALARM_DEACTIVATED();
        // Switch to ALARM_ACTIVE state if the Door-Circuit is activated
        else if(door_state == ALARM_IS_TRIGGERED) 
          enter_ALARM_ACTIVE();
        break;

      case ALARM_ACTIVE:
        // Set variables for ALARM_ACTIVE state
        alarm_active = true;
        alarm_timed_out = false;
        
        // Toggle the relay_state when Timer
        if(millis() >= relay_last_toggle_time + RELAY_TOGGLE_INTERVAL){
          // Toggle Relay State
          relay_state = !relay_state;
          relay_last_toggle_time = millis();
        }

        // Switch to ALARM_DEACTIVATED state if the Key-Switch is deactivated
        if(key_switch_state != ALARM_IS_ARMED) 
          enter_ALARM_DEACTIVATED();
        // Switch to ALARM_TIMEOUT state if the ALARM_ACTIVE state is longer active than ALARM_MAX_ACTIVE_TIME
        else if(door_state != ALARM_IS_TRIGGERED) 
          enter_ALARM_ACTIVE_COUNTDOWN();
        break;

      case ALARM_ACTIVE_COUNTDOWN:
        // Set variables for ALARM_ACTIVE state
        alarm_active = true;
        alarm_timed_out = false;
        
        // Toggle the relay_state when Timer
        if(millis() >= relay_last_toggle_time + RELAY_TOGGLE_INTERVAL){
          // Toggle Relay State
          relay_state = !relay_state;
          relay_last_toggle_time = millis();
        }

          //The Alarm was triggered again. Reset the Cooldown
        if(door_state == ALARM_IS_TRIGGERED)
          enter_ALARM_ACTIVE();
        // Switch to ALARM_DEACTIVATED state if the Key-Switch is deactivated
        else if(key_switch_state != ALARM_IS_ARMED) 
          enter_ALARM_DEACTIVATED();
        // Switch to ALARM_TIMEOUT state if the ALARM_ACTIVE state is longer active than ALARM_MAX_ACTIVE_TIME
        else if(millis() >= alarm_activated_time + ALARM_MAX_ACTIVE_TIME) 
          enter_ALARM_ARMED();
        break;

      /*
      case ALARM_TIMEOUT:
        alarm_active = false;
        relay_state = false;
        alarm_timed_out = false;

        // Switch to ALARM_DEACTIVATED state if the Key-Switch is deactivated
        if(key_switch_state != ALARM_IS_ARMED) 
          enter_ALARM_DEACTIVATED();
        break;
      */

      default:
        enter_ALARM_DEACTIVATED();
        break;
    }

    
  // Write Relay State
  digitalWrite(RELAY_PIN, relay_state);
  }
}
NOCOMNCVCCGNDINLED1PWRRelay Module