#ifndef _SPHINX_CONTROLLER
#define _SPHINX_CONTROLLER

#define OF_ADDON_USING_OFXTHREAD

#include "ofAddons.h"
#include "ofMain.h"
#include "RtAudio.h"

#include "samplerate.h"

#include <vector.h>
#include <stdio.h>
#include <string.h>
#include <fstream>

// For Sphinx-3 decoding, prevent multiple inclusions
#ifndef _SPHINX_HEADERS_
#define _SPHINX_HEADERS_
// Sphinx libraries are C, wrap in the following to get them linking
extern "C" {
	#include "s3_decode.h"
}
#endif

//the size of our buffer
#define SP_BUFFER_SIZE 256

//the max length of audio in samples
//80000 at 16000Hz is 5 seconds
#define MAX_PROCESS_BUFFER_SIZE 80000 


class SphinxController : public ofxThread{

	public:
		SphinxController();
		~SphinxController();
		
		//==================================== methods
		
		// initialize everything we need to do
		bool sphinxSetup(string config_file, float sampleRate, int deviceID = 0);
		void stopDecoding();
		
		// do some stuff
		double apply_gain (float * data, long frames, int channels, double max, double gain);
		//get data from sphinx
		void receiveHypothesis(char *hypothesis);
		//callback from rtaudio
		int prepare_audio_data(char *buffer, int bufferSize, void *data);
										
		//==================================== variables
		// keep a pointer to our audio that will get the sound and send it to sphinx
		RtAudio *audio;

		int	src_error; // store any error value from src
		std::vector<short>  sphinxSamples; // Used to handoff samples to Sphinx
		std::vector<short>  sphinxSamplesBacklog; //when the thread is locked!
		
		string current_hypo;
		
		float	float_sphinxSamplesOut[SP_BUFFER_SIZE];
		short	convertedData[SP_BUFFER_SIZE];
		short	processMe[MAX_PROCESS_BUFFER_SIZE];
		
		int		bufferSize;	// How big m_pSphinxSamples is
		
		short * inputPtr;
		int		nSamples;
		int		nFrames;
		
		int		samp_err_int;
		int		samp_err_int_ptr;		
		bool	bRecordAudio;
		bool	bDecodingStarted;
		
	protected:
		void processAudioChunk();
		void threadedFunction();

		bool initSphinx(string config_file);
		bool initAudio(float sampleRate, int deviceID);
		


		SRC_DATA src_data;
		SRC_STATE *src_state_ptr;

		// ptr to Sphinx decoder
		s3_decode_t* pSphinxDecoder;
		s3_decode_t decoder; // the decoder
		// pointer to the Sphinx front-end, this is returned by the pSphinxFrontEnd = fe_init_auto(); 
		fe_t* pSphinxFrontEnd;
};

#endif