/*
 
 //#######################################################################################
 //Class to insert Midiclock messages into a given MidiBuffer, suitable for block
 //based audio callbacks. The class can act on position jumps e.g. "Loops" by sending a 
 //positioning message.
 //NOTE: No ballistik came in to play so I wouldn't recommend using it to drive a mechanical
 //tape deck!!!
 //
 //solar3d-software, April- 10- 2012
 //#######################################################################################
 
 */
#ifndef __JK_MIDICLOCK
#define __JK_MIDICLOCK

#include "../JuceLibraryCode/JuceHeader.h"

//#include "Includes.h"

class JK_MidiClock
{
public:
    JK_MidiClock();
    
	void setPositionJumpThreshold(const double ms)						{posChangeThreshold = ms / 1000.0;}
	double getPositionJumpThreshold()									{return posChangeThreshold;}
    void setFollowSongPosition(const bool shouldFollow)                 {followSongPosition = shouldFollow;}
	bool getFollowSongPosition()										{return followSongPosition;}
    void setOffset(const int offset)                                    {ppqOffset = offset;}
    int  getOffset()                                                    {return ppqOffset;}
    
    void generateMidiclock(AudioPlayHead::CurrentPositionInfo &lastPosInfo,
                           MidiBuffer* midiBuffer,
                           const int bufferSize,
                           const double sampleRate);
    
    //=================================================================================================
    juce_UseDebuggingNewOperator
    
private:
    inline int64 roundToInt64 (const double val) noexcept
	{
		return (val - floor(val) >= 0.5) ? (int64)(ceil(val)) : (int64)(floor(val));
	}
	
	
	bool   wasPlaying;
	double syncPpqPosition;
	double posChangeThreshold;
    double ppqToStartSyncAt;
    bool   followSongPosition;   
	uint8  syncFlag;
    int    ppqOffset;
	
    static const int cycleEnd_   = 1;
    static const int startSlave_ = 2;
	
	ScopedPointer <MidiMessage> clockMessage;
	ScopedPointer <MidiMessage> continueMessage;
	ScopedPointer <MidiMessage> stopMessage;
	ScopedPointer <MidiMessage> songPositionMessage;
    
	void sendSongPositionPointerMessage(const double ppqPosition, const int posInBuffer, MidiBuffer* buffer);
    
	bool positionJumped(const double lastPosInPPQ, const double currentPosInPPQ, 
                        const double sampleRate, const double ppqPerSample);
    
	double getNearestSixteenthInPPQ(const double ppqPosition)  	           {return ceil(ppqPosition * 4.0) / 4.0;}
    
	JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JK_MidiClock);
};
#endif
