/*-----------------------------------------------------------------------------

� 1999, Steinberg Soft und Hardware GmbH, All Rights Reserved

-----------------------------------------------------------------------------*/

#include <reverb/reverb.hpp>
#include "plugin.hpp"
#include <cstdlib>
#include <cstdio>

#define MAX_ORDER	4

enum {ORDER, SIZE_1, SIZE_2, SIZE_3, SIZE_4, FEEDBACK_DELAY_MIN, FEEDBACK_DELAY_XAX, FEEDBACK_GAIN};

AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
{
	return new Plugin (audioMaster);
}

//-----------------------------------------------------------------------------
Plugin::Plugin(audioMasterCallback audioMaster)
: AudioEffectX(audioMaster, 1, NUM_PARMS)	// 1 program, 1 parameter only
, m_reverb_1({DELAY_MAX, DELAY_MAX, DELAY_MAX, DELAY_MAX}, DELAY_MAX, 0)
, m_reverb_2({DELAY_MAX, DELAY_MAX, DELAY_MAX, DELAY_MAX}, DELAY_MAX, 0)
{
	sampleRate = 48000;
	setNumInputs(2);		// stereo in
	setNumOutputs(2);		// stereo out
	setUniqueID('DLY1');	// identify
	canMono();				// makes sense to feed both inputs with the same signal
	canProcessReplacing();	// supports both accumulating and replacing output
	strcpy(programName, "Default");	// default program name

	m_feedback_delay[0] = 0;
	m_feedback_delay[1] = 0;

	m_params[0] = new Param("Order", "", 0, 4, 4);
	m_params[1] = new Param("Delay 1", "ms", 0, 1000, 50);
	m_params[2] = new Param("Delay 2", "ms", 0, 1000, 100);
	m_params[3] = new Param("Delay 3", "ms", 0, 1000, 250);
	m_params[4] = new Param("Delay 4", "ms", 0, 1000, 500);
	m_params[5] = new Param("Feedback Delay Min", "ms", 0, 1000, 100);
	m_params[6] = new Param("Feedback Delay Max", "ms", 0, 1000, 200);
	m_params[7] = new Param("Feedback Gain", "%", 0, 100, 0);
}

//-----------------------------------------------------------------------------------------
Plugin::~Plugin()
{
	// nothing to do here
}

//-----------------------------------------------------------------------------------------
void Plugin::setProgramName(char *name)
{
	strcpy(programName, name);
}

//-----------------------------------------------------------------------------------------
void Plugin::getProgramName(char *name)
{
	strcpy(name, programName);
}

//-----------------------------------------------------------------------------------------
void Plugin::setParameter(VstInt32 index, float value)
{
	switch(index)
	{
		case ORDER:
			break;

		case SIZE_1:
		case SIZE_2:
		case SIZE_3:
		case SIZE_4:
		{
			double p = m_params[index]->fromSlider(value);
			uint delay = (uint)(p*sampleRate/1000);
			m_reverb_1.setDelay(delay, index - SIZE_1);
			m_reverb_2.setDelay(delay, index - SIZE_1);
			break;
		}

		case FEEDBACK_GAIN:
		{
			double p = m_params[index]->fromSlider(value)/100;
			m_reverb_1.setFeedbackGain(p);
			m_reverb_2.setFeedbackGain(p);
			break;
		}

		case FEEDBACK_DELAY_MIN:
		case FEEDBACK_DELAY_XAX:
		{
			double p = m_params[index]->fromSlider(value);
			uint delay = (uint)(p*sampleRate/1000);
			m_feedback_delay[index-FEEDBACK_DELAY_MIN] = delay;
			m_reverb_1.setFeedbackDelay(m_feedback_delay[0], m_feedback_delay[1]);
			m_reverb_2.setFeedbackDelay(m_feedback_delay[0], m_feedback_delay[1]);
			break;
		}
		
	}

}

//-----------------------------------------------------------------------------------------
float Plugin::getParameter(VstInt32 index)
{
	float value = 0;
	
	switch(index)
	{
	case ORDER:
	case SIZE_1:
	case SIZE_2:
	case SIZE_3:
	case SIZE_4:
	case FEEDBACK_GAIN:
	case FEEDBACK_DELAY_MIN:
	case FEEDBACK_DELAY_XAX:
		value = m_params[index]->getSlider();
		break;


	}
	return value;
}

//-----------------------------------------------------------------------------------------
void Plugin::getParameterName(VstInt32 index, char *label)
{
	switch(index)
	{
		case ORDER:
		case SIZE_1:
		case SIZE_2:
		case SIZE_3:
		case SIZE_4:
		case FEEDBACK_DELAY_MIN:
		case FEEDBACK_DELAY_XAX:
		case FEEDBACK_GAIN:
			strcpy(label,m_params[index]->name().c_str());
			break;
		default:
			strcpy(label,"Unknown");
			break;		
	}
}

//-----------------------------------------------------------------------------------------
void Plugin::getParameterDisplay(VstInt32 index, char *text)
{

	switch(index)
	{
		case ORDER:
		case SIZE_1:
		case SIZE_2:
		case SIZE_3:
		case SIZE_4:
		case FEEDBACK_DELAY_MIN:
		case FEEDBACK_DELAY_XAX:
		case FEEDBACK_GAIN:
			sprintf(text, "%f", m_params[index]->getParameter());
			break;
	}
}

//-----------------------------------------------------------------------------------------
void Plugin::getParameterLabel(VstInt32 index, char *label)
{
	switch(index)
	{
		case ORDER:
		case SIZE_1:
		case SIZE_2:
		case SIZE_3:
		case SIZE_4:
		case FEEDBACK_DELAY_MIN:
		case FEEDBACK_DELAY_XAX:
		case FEEDBACK_GAIN:
			strcpy(label,m_params[index]->unit().c_str());
			break;
	}
}

//-----------------------------------------------------------------------------------------
void Plugin::processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames)
{
    float *in1  =  inputs[0];
    float *in2  =  inputs[1];
    float *out1 = outputs[0];
    float *out2 = outputs[1];

	m_reverb_1.process_multi(in1, out1, sampleFrames);
	m_reverb_2.process_multi(in2, out2, sampleFrames);
}

//-----------------------------------------------------------------------------------------
void Plugin::setSampleRate(float sampleRate)
{
	this->sampleRate = sampleRate;
	sprintf(dbgStr, "Sample Rate = %f",sampleRate);
//	OutputDebugString(dbgStr);
}

//-----------------------------------------------------------------------------------------
void Plugin::setBlockSize(VstInt32 blockSize)
{
	this->blockSize = blockSize;
	sprintf(dbgStr, "Block Size = %d",blockSize);
//	OutputDebugString(dbgStr);
}
