#line 1 "C:\\Users\\espi_\\Documents\\Arduino\\4. Bell Systems\\1. Main Projects\\Project - Vesper\\bellEngine.hpp"
// MELODY PLAYBACK WILL BE HANDLED HERE
#include <vector>

extern melody_attributes melody;

// Define a structure to track active solenoids
struct ActiveRelay {
    uint8_t relayIndex;      // Index of the relay
    uint64_t activationTime; // Activation start time
    uint16_t duration;       // Duration for which it should remain active
};

// Array of durations for each relay (configure remotely)
uint16_t relayDurations[16] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90};
// Vector to track active solenoids
std::vector<ActiveRelay> activeRelays;



void loop_playback(std::vector<uint16_t> &melody_steps);
void bellEngine(void *parameter);
void relayControlTask(void *param);
void itsHammerTime(uint16_t note);
void turnOffRelays(uint64_t now);

void bellEngine(void *parameter) {
	// SETUP TASK
	for (;;) {
		// Playback until stopped (Completes AT LEAST 1 full loop)
		loop_playback(melody_steps);
 /*
		UBaseType_t highWaterMark = uxTaskGetStackHighWaterMark(NULL);
		Serial.print("Stack high water mark: ");
		Serial.println(highWaterMark);
 */
	}
}

// Task to deactivate relays dynamically
void relayControlTask(void *param) {
	while (true) {
      uint64_t now = millis();
      // Iterate through active relays and deactivate those whose duration has elapsed
      for (auto it = activeRelays.begin(); it != activeRelays.end();) {
          if (now - it->activationTime >= it->duration) {
              relays.digitalWrite(it->relayIndex, HIGH); // Deactivate the relay
              it = activeRelays.erase(it);              // Remove from the active list
          } else {
              ++it; // Move to the next relay
          }
      }

      vTaskDelay(pdMS_TO_TICKS(10)); // Check every 10ms
  }
}


void loop_playback(std::vector<uint16_t> &melody_steps) {

	while(melody.isPlaying && !melody.isPaused){

		// iterate through the beats and call the bell mechanism on each beat
		for (uint16_t note : melody_steps) {
			if (melody.hardStop) return;
			itsHammerTime(note);
			int tempo = melody.speed;
			vTaskDelay(pdMS_TO_TICKS(tempo));
		}

		Serial.println("SINGLE LOOP OVER.");
    //if (!melody.isPlaying) break;                  // Stop playback only after completing the loop
	}
}


// Function to activate relays for a specific note
void itsHammerTime(uint16_t note) {
    uint64_t now = millis();

    for (uint8_t i = 0; i < 16; i++) {
        if (note & (1 << i)) { // Check if this relay needs to activate
            relays.digitalWrite(i, LOW); // Activate the relay

            // Add to the activeRelays list
            activeRelays.push_back({i, now, relayDurations[i]});
        }
    }
}
