#pragma once

#include "ITrack.h"

//--------------------------------------------------------------
class Track : public ITrack
{
  public:
  struct MidiNoteEvent
  {
    int64_t tick;         // The tick at which the event occurs
    int     pitch;        // The MIDI note number (0-127)
    int     velocity;     // The velocity of the note (0-127)
    int     track;        // The track number (0-based index)
    int     channel;      // The MIDI channel (1-16, or 0 for no channel)
    bool    noteOn;       // True if the event is a Note On event, false otherwise (Note Off)
  };
  struct MidiTempoEvents
  {
    int64_t   tick;                           // The tick at which the tempo change occurs
    double    microsecondsPerQuarterNote;     // The new tempo in microseconds per quarter note
    Timestamp timeMs;                         // The time in milliseconds at which the tempo change occurs
  };

  public:
  Track()                                = default;     // Default constructor
  virtual ~Track()                       = default;     // Default destructor
  Track(const Track &obj)                = delete;      // Copy constructor
  Track(Track &&obj) noexcept            = delete;      // Move constructor
  Track &operator=(const Track &obj)     = delete;      // Copy assignment operator
  Track &operator=(Track &&obj) noexcept = delete;      // Move assignment operator

  // --- File management ---
  void                    loadFromFile(const std::filesystem::path &filePath) override;     // Load a MIDI file from disk
  void                    loadFromMemory(std::span<uint8_t> midiBytes) override;            // Load a MIDI file from memory
  void                    clear() override;                                                 // Clear the track data
  [[nodiscard]] bool      isLoaded() const override;                                        // Check if a MIDI file is loaded
  [[nodiscard]] Timestamp getDuration() const override;                                     // Get the duration of the track in milliseconds

  void debug() override;     // Debug function to print the track data

  // --- Rendering ---
  [[nodiscard]] TrackWindow getTrackWindow(Timestamp startTime, Timestamp endTime) const override;     // Get notes in a given time window

  protected:
  mutable std::mutex m_mtx;     // Mutex to protect access to the data structures

  std::vector<MidiNoteEvent>   m_noteEvents;      // Vector to store note events
  std::vector<MidiTempoEvents> m_tempoEvents;     // Vector to store tempo events

  // Vectors to store note events sorted by start and end time for efficient retrieval
  std::vector<NoteEvent> m_notesByStart;     // Vector to store note events sorted by start time
  std::vector<NoteEvent> m_notesByEnd;       // Vector to store note events sorted by end time
};
//--------------------------------------------------------------
