/*!
	Main MATLAB interface

	@param[in,out] nlhs		Number of left hand (output) matrices.
	@param[in,out] plhs		Pointers to left hand (output) matrices.
	@param[in] nrhs			Number of right hand (input) matrices.
	@param[in] prhs			Pointers to right hand (input) matrices.
*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
	//persistence and data variables
	Persistence1D p;
	std::vector<float> data; 

	//Variables to store persistence results
	std::vector<int> minIndices; 
	std::vector<int> maxIndices; 
	std::vector<TPairedExtrema> pairs;
	float gminValue;
	int gminIndex;
	
	//Assumption: Vector data lives in phrs[0]
	//Any deviation from this is not tolerated.

	//prhs - right hand - input - MATLAB standard naming convention
	//plhs - left hand - output
	if (!CheckInput(nlhs, plhs, nrhs, prhs)) return;

#ifdef _DEBUG	
    mexPrintf("Copying input data...\n");
#endif
	WriteInputToVector(prhs, data);
	
#ifdef _DEBUG
	WriteVectorToMexOutput(data);
#endif
	
#ifdef _DEBUG
    mexPrintf("Running Persistence1D...\n");
#endif
	p.RunPersistence(data);

#ifdef _DEBUG
    mexPrintf("Done.\n");
	mexPrintf("Getting results...\n");
#endif

    p.GetPairedExtrema(pairs, NO_FILTERING , MATLAB_INDEXING);
    gminIndex = p.GetGlobalMinimumIndex(MATLAB_INDEXING);
	gminValue = p.GetGlobalMinimumValue();
	p.GetExtremaIndices(minIndices, maxIndices, NO_FILTERING, MATLAB_INDEXING);

#ifdef _DEBUG
	mexPrintf("Done.\n");
	mexPrintf("Writing results to MATLAB...\n");
#endif
    	
	plhs[0] = VectorToMxSingleArray(minIndices);
	plhs[1] = VectorToMxSingleArray(maxIndices);
	plhs[2] = VectorToMxSingleArray(pairs);
	plhs[3] = ScalarToMxSingleArray(gminIndex);
	plhs[4] = ScalarToMxSingleArray(gminValue);

#ifdef _DEBUG	
	mexPrintf("Done.\n");
#endif
	return;
}
int main()
{
	//Create some data
	vector< float > data;
	data.push_back(2.0);   data.push_back(5.0);   data.push_back(7.0);
	data.push_back(-12.0); data.push_back(-13.0); data.push_back(-7.0);
	data.push_back(10.0);  data.push_back(18.0);  data.push_back(6.0);
	data.push_back(8.0);   data.push_back(7.0);   data.push_back(4.0);

	//Run persistence on data - this is the main call.
	Persistence1D p;
	p.RunPersistence(data);

	//Get all extrema with a persistence larger than 10.
	vector< TPairedExtrema > Extrema;
	p.GetPairedExtrema(Extrema, 10);

	//Print all found pairs - pairs are sorted ascending wrt. persistence.
	for(vector< TPairedExtrema >::iterator it = Extrema.begin(); it != Extrema.end(); it++)
	{
		cout << "Persistence: " << (*it).Persistence
			 << " minimum index: " << (*it).MinIndex
			 << " maximum index: " << (*it).MaxIndex
			 << std::endl;
	}

	//Also, print the global minimum.
	cout << "Global minimum index: " << p.GetGlobalMinimumIndex() 
		 << " Global minimum value: " << p.GetGlobalMinimumValue() << endl;

	/*
		Note that filtering and printing can also be done with one single function call:
		p.PrintResults(10);
	*/

	return 0;
}