#pragma once
#include "WaveTableSynth.h"

namespace sf {
  enum struct SequenceCommand {
    Note
  };

  struct SequenceData 
  {
    SequenceData () : step(0.0f),pitch(0.0f),velocity(0.0f),gateTime(0.0f){};
    SequenceData(SequenceCommand c,int s,float p,float v,int g )
      : cmd(c),step(s),pitch(p),velocity(v),gateTime(g) {};
    SequenceData(SequenceData& src)
      : cmd(src.cmd),step(src.step),pitch(src.pitch),velocity(src.velocity),gateTime(src.gateTime) {}

    SequenceData(SequenceData&& src)
      : cmd(std::move(src.cmd)),step(std::move(src.step)),pitch(std::move(src.pitch)),velocity(std::move(src.velocity)),gateTime(std::move(src.gateTime)) {}

    SequenceData& operator=(SequenceData& src)
    {
      if(this != &src)
      {
        cmd = src.cmd;
        step = src.step;
        pitch = src.pitch;
        velocity = src.velocity;
        gateTime = src.gateTime;
      }
      return *this;
    }

    SequenceData& operator=(SequenceData&& src)
    {
      if(this != &src)
      {
        cmd = std::move(src.cmd);
        step = std::move(src.step);
        pitch = std::move(src.pitch);
        velocity = std::move(src.velocity);
        gateTime = std::move(src.gateTime);
      }
      return *this;
    }

    SequenceCommand cmd;
    int step;
    float pitch;
    float velocity;
    int gateTime;
  };

  typedef std::vector<SequenceData> SequenceDatasType;
  typedef std::vector<SequenceDatasType> SequenceTracksType;


  struct Sequencer
  {
    enum struct Status
    {
      Play,Stop,Pause
    };

    Sequencer(Synthesizer& synth,WAVEFORMATEXTENSIBLE& format);
    void Process();
    ~Sequencer();

    float TimeBase() const;
    void TimeBase(float v); 

    float Tempo() const;
    void Tempo(float v);

    void Play();
    void Pause();
    void Stop();
    SequenceTracksType& SequenceTracks();
  private:
    struct impl;
    std::unique_ptr<impl> impl_;
  };
}
