#pragma once

#include "trackDefs.h"

#include <mutex>

namespace track
{
//--------------------------------------------------------------
class TrackLockProxy final
{
  public:
  TrackLockProxy()                                         = delete;      // Default constructor
  ~TrackLockProxy()                                        = default;     // Default destructor
  TrackLockProxy(const TrackLockProxy &obj)                = delete;      // Copy constructor
  TrackLockProxy(TrackLockProxy &&obj) noexcept            = default;     // Move constructor
  TrackLockProxy &operator=(const TrackLockProxy &obj)     = delete;      // Copy assignment operator
  TrackLockProxy &operator=(TrackLockProxy &&obj) noexcept = default;     // Move assignment operator

  explicit TrackLockProxy(std::mutex &mtx, NotesView notes);     // Constructor

  const Note &operator[](size_t index) const;     // Access a note by index

  [[nodiscard]] ActiveNotes getActiveNotesAt(Seconds currentTime,     // Get the active notes at a specific time with a lookahead window
                                             Seconds lookaheadWindow) const;
  void                      getActiveNotesAt(Seconds      currentTime,     // Get the active notes at a specific time with a lookahead window
                                             Seconds      lookaheadWindow,
                                             ActiveNotes &outNotes) const;

  [[nodiscard]] Seconds getDuration() const;     // Get the duration of the track

  // Utility functions to access the notes into for-range loops or other algorithms
  [[nodiscard]] NotesView get() const noexcept;       // Get the span of notes
  [[nodiscard]] auto      begin() const noexcept;     // Get the first iterator of the notes
  [[nodiscard]] auto      end() const noexcept;       // Get the end iterator of the notes
  [[nodiscard]] bool      empty() const noexcept;     // Check if the notes span is empty
  [[nodiscard]] size_t    size() const noexcept;      // Get the size of the notes span

  protected:
  std::unique_lock<std::mutex> m_lock;     // Keeps the mutex locked for the lifetime of the proxy

  NotesView m_notes;     // Span of notes to access without copying the data
};
//--------------------------------------------------------------
}     // namespace track
