bool buttonCurrentState[3] = {HIGH, HIGH, HIGH};
bool buttonLastState[3] = {HIGH, HIGH, HIGH};
unsigned long buttonDownMillis[3] = {0, 0, 0};
unsigned long buttonCurrentHoldTime[3] = {0, 0, 0};
bool buttonFired[3] = {false, false, false};
bool buttonHoldFired[3] = {false, false, false};
unsigned long lastButtonPress[3] = {0, 0, 0};

void buttonAction(byte btn) {
  lastSwitchSource[btn] = 0;
  relaisToggle(btn);
  switch (btn) {
    case 0:
      if (strlen(mqtt_topic_out_1) > 0) mqttclient.publish(mqtt_topic_out_1, mqtt_payload_out_1, mqtt_btnRetain);
      break;
    case 1:
      if (strlen(mqtt_topic_out_2) > 0) mqttclient.publish(mqtt_topic_out_2, mqtt_payload_out_2, mqtt_btnRetain);
      break;
    case 2:
      if (strlen(mqtt_topic_out_3) > 0) mqttclient.publish(mqtt_topic_out_3, mqtt_payload_out_3, mqtt_btnRetain);
      break;
  }

  if (led_enabled[btn]) {
    // blink LED when hold action is triggered
    bool ledState = digitalRead(leds_pins[btn]);
    digitalWrite(leds_pins[btn], !ledState);
    delay(250);
    digitalWrite(leds_pins[btn], ledState);
  }
}

void buttonHoldAction(byte btn) {
  if (hldToRel[btn] > 0) {
    relaisToggle( hldToRel[ btn - 1 ] );
  }
  switch (btn) {
    case 0:
      if (strlen(mqtt_topic_out_hold_1) > 0) mqttclient.publish(mqtt_topic_out_hold_1, mqtt_payload_out_hold_1, mqtt_btnRetain);
      break;
    case 1:
      if (strlen(mqtt_topic_out_hold_2) > 0) mqttclient.publish(mqtt_topic_out_hold_2, mqtt_payload_out_hold_2, mqtt_btnRetain);
      break;
    case 2:
      if (strlen(mqtt_topic_out_hold_3) > 0) mqttclient.publish(mqtt_topic_out_hold_3, mqtt_payload_out_hold_3, mqtt_btnRetain);
      break;
  }

  if (led_enabled[btn]) {
    // blink LED when hold action is triggered
    bool ledState = digitalRead(leds_pins[btn]);
    digitalWrite(leds_pins[btn], !ledState);
    delay(250);
    digitalWrite(leds_pins[btn], ledState);
  }
}

void checkButtonStates() {
  for (int i = 0; i < BUTTONS_COUNT; i++) {
    if (button_enabled[i]) checkButtonState(i);
  }
}

void checkButtonState(byte btn) {
  buttonCurrentHoldTime[btn] = millis() - buttonDownMillis[btn];
  buttonCurrentState[btn] = digitalRead(buttons_pins[btn]);
  if (buttonCurrentState[btn] == LOW && buttonLastState[btn] == HIGH) { // button was unpressed and is millis() pressed
    buttonDownMillis[btn] = millis();
    buttonLastState[btn] = buttonCurrentState[btn];
  }
  else if (buttonCurrentState[btn] == LOW && buttonLastState[btn] == LOW) { // button is held
    if ( buttonCurrentHoldTime[btn] > debounceTime ) {
      buttonLastState[btn] = buttonCurrentState[btn];
      if ( buttonCurrentHoldTime[btn] > buttonHoldTime && !buttonHoldFired[btn] ) {
        // button is held longer
        if ( (millis() - lastButtonPress[btn]) > 500 ) { // avoid double triggering
          lastButtonPress[btn] = millis();
          Serial.print("Button ");
          Serial.print(btn + 1);
          Serial.println(" long pressed");
          buttonHoldAction(btn);
          buttonHoldFired[btn] = true;
        }
      }
    }
  }
  else if (buttonCurrentState[btn] == HIGH && buttonLastState[btn] == LOW) { // button is released again
    if (buttonCurrentHoldTime[btn] > debounceTime) {          // entprellung
      buttonLastState[btn] = buttonCurrentState[btn];
      if (!buttonHoldFired[btn] && !buttonFired[btn]) {
        if ( (millis() - lastButtonPress[btn]) > 500 ) { // avoid double triggering
          lastButtonPress[btn] = millis();
          Serial.print("Button ");
          Serial.print(btn + 1);
          Serial.println(" short pressed");
          buttonAction(btn);
        }
      }
      buttonFired[btn] = false;
      buttonHoldFired[btn] = false;
    }
  }
}

