#pragma once

#include <chrono>
#include <cstdint>
#include <span>
#include <string>
#include <vector>

namespace track
{
//--------------------------------------------------------------
using Seconds = std::chrono::duration<double>;

struct Note;     // Forward declaration of the Note structure
using NotesView   = std::span<const Note>;
using NotesBuffer = std::vector<Note>;
//--------------------------------------------------------------
// The Note structure represents a single MIDI note event with
// its properties.
struct Note
{
  uint8_t channel;      // MIDI channel (0-15)
  uint8_t pitch;        // Midi note number (0-127)
  uint8_t velocity;     // Velocity of the note event (0-127)

  std::string name;          // Name of the note without octave (e.g., "C", "D#")
  int         octave;        // Octave number of the note (e.g., 4 for C4)
  float       frequency;     // Frequency of the note in Hz (e.g., 440.0 for A4)

  Seconds startTime;     // Start time of the note event (time when the note starts)
  Seconds endTime;       // End time of the note event (time when the note ends)
};
//--------------------------------------------------------------
// The ActiveNotes structure holds two buffers of notes:
//   - playing notes: startTime <= t < endTime
//   - upcoming notes: t + window <= startTime < t + window + upcomingWindow
// This structure is used to efficiently manage and access the notes
// that are relevant for playback at a given time.
struct ActiveNotes
{
  NotesBuffer playing;      // Currently playing notes (t <= startTime < t + window)
  NotesBuffer upcoming;     // Upcoming notes (t + window <= startTime < t + window + upcomingWindow)
};
//--------------------------------------------------------------
}     // namespace track
