// Copyright (c) 2018 Giorgos Vougioukas
//
// The license can be found in the LICENSE file.

#ifndef _EUTERPE_MAIN_LOOP_H_
#define _EUTERPE_MAIN_LOOP_H_

#if defined(_WIN32)
  #include <windows.h>
  #include <process.h>
#else
  #include "WDL/swell/swell.h"
#endif

#include "euterpe/euterpe_plugin.h"
#include "euterpe/buffer_queue.h"

#include "WDL/MersenneTwister.h"
#include "WDL/mutex.h"
#include "WDL/ptrlist.h"
#include "WDL/queue.h"
#include "WDL/wdlstring.h"

#define RSE_PLAYBACK_MAX_QUEUE 505

class RSE_MainLoop
{
public:
  RSE_MainLoop();
  ~RSE_MainLoop();

  void AddTrack(const char *track);
  void Seek(double time);
  double GetVolume();
  void SetVolume(double db);
  void ToggleMute();

  void Pause();
  void Previous();
  void Next();
  void Play(int track_num = -1, bool reset_stop_after_current = true);
  void Stop();
  void StopAfterCurrent();
  bool HasStopAfterCurrent() const;
  bool IsPlaying() const;
  bool IsPaused() const;
  bool IsMuted() const;

  double GetDuration() const;
  double GetRunningTime() const;

  void UpdatePlayList(WDL_PtrList_DeleteOnDestroy<char> *pl);
  void SetKillRegion(WDL_HeapBuf *kill_region);
  void GetKillRegion(WDL_HeapBuf **kill_region);

  void AddToQueue(const char *track);
  void RemoveFromQueue();
  void ClearQueue();
  int TracksInQueue() const;
  int NextInQueue() const;

  void RemoveAll();
  void SetCurrentTrack(int index);
  int GetCurrentTrack() const;

  void ToggleShuffle();
  void ToggleRepeat();
  bool IsShuffleOn() const;
  bool IsRepeatOn() const;

  const char *GetCurrentFilename() const;

  void ToggleTime();
  void SetTimeElapsed(bool elapsed);
  bool IsTimeElapsed() const;

  void EmptyBufferQueue();

  void AudioOutput(WDL_TypedBuf<SAM> *output, int frame_count, int nch);
  int Run();

private:
  bool IsDrained() const; // Check if we have reached EOF
  bool WantMore() const; // Check if you want to do buffering
  bool DoBuffering(int buffer_size = 4096); // Fill buffer queue with data

  WDL_FastString m_file;

  bool m_is_paused;
  double m_db;
  double m_last_db;
  bool m_is_muted;

  RSE_IFileInput *m_audio_input;
  mutable double m_running_time;
  bool m_eof;

  RSE_BufferQueue m_bq;
  int m_bq_max_duration_ms;
  double m_duration;

  WDL_TypedBuf<SAM> m_buffer;

  WDL_PtrList_DeleteOnDestroy<char> *m_playlist;
  WDL_PtrList<char> m_playback_queue;

  int m_current_track;
  bool m_is_repeat_on;
  bool m_is_shuffle_on;
  MTRand m_mt;
  bool m_is_time_elapsed;
  bool m_has_stop_after_current;
  WDL_HeapBuf *m_kill_region;
};

#endif // _EUTERPE_MAIN_LOOP_H_
