#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
#include <fft_utils.h>
#include <ReportTree.h> 
#include <event_utils.h>
#include <o8dlg.h>
//put additional include files here

//put your own support static functions here

/***************************************************************************************
/// Modification Log :
///	Folger 07/28/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
***************************************************************************************/

#define _TABLE_NAME "Hilbert"
#define _TABLE_LABEL _L("Hilbert Transform")

#define _HILBERT_SNAME "Hilbert"
#define _HILBERT_LNAME _L("Hilbert")
#define _ANLYTIC_SNAME "AnaSign"
#define _ANLYTIC_LNAME _L("Analytic Signal")
 
enum{
	_HILBERT_RESULT_TABLE  = 100,
};

enum{
	_HILBERT_HIBERT = 101,
	_HILBERT_ANALYTIC
};


	
	///Sandy 2008-10-20 add checking centralize function
static bool _check_inputs(TreeNode trGetN, string& strErrMsg)
{
	if(!trGetN.hil.nVal && !trGetN.ansig.nVal)
	{
		strErrMsg = XFERR_HILBERT_NO_OUTPUT;
		
		return false;
	}
	
	if(!get_error_for_input_double_vector(trGetN.ix, strErrMsg))
		return false;
	
	return true;
}
static void _hilbert_in_freqency_domain(vector<complex>& vSignal)
{
	int nSize = vSignal.GetSize();
	
	vector vRe(nSize), vIm(nSize), vTmp( (nSize-1)/2 );
	vRe = 0;
	
	vTmp = -1;
	vIm.SetSubVector(vTmp, 1);
	vTmp = 1;
	vIm.SetSubVector(vTmp, nSize/2+1);
	
	vIm[0] = 0;
	if(nSize%2 == 0)
		vIm[nSize/2] = 0;

	vector<complex> vH(vRe, vIm);
    vSignal *= vH;
}

//------ Folger 07/28/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
static	string	_get_output_range_comments(const vector& ix)
{
	return _TABLE_LABEL + " of " + get_input_data_range_string(ix.GetSourceDataRange());
}
//------ End BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS


void hilbert(const vector& ix, const int& hil, const int& ansig, ReportData& rd)
{
	if(!rd || !ix || ix.GetSize() < 1 || !(hil || ansig))
		XF_THROW(XFERR_RUNTIME_EXCEPTION); 
	vector vHil;
	vHil = ix;
	fft_real(vHil.GetSize(), vHil);
	vector<complex> vFFT(vHil.GetSize());
	fft_hermitian_to_complex(vHil.GetSize(), vHil, vFFT);
	_hilbert_in_freqency_domain(vFFT);
	fft_complex(vFFT.GetSize(), vFFT, FFT_BACKWARD);
	vFFT.GetReal(vHil);
	int nSize = vHil.GetSize();
	vHil /= nSize;
	
	ReportTable rt = rd.CreateTable(_TABLE_NAME, _get_output_range_comments(ix), _HILBERT_RESULT_TABLE);
	
	if(hil)
		rt.AddColumn(vHil,_HILBERT_SNAME, _HILBERT_HIBERT, _HILBERT_LNAME); 
	if(ansig)
	{
		vector<complex> vAnalytic(ix,vHil);
		rt.AddColumn(vAnalytic, _ANLYTIC_SNAME, _HILBERT_ANALYTIC, _ANLYTIC_LNAME);
	}
	
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int hilbert_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return hilbert_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	//if(!trGetN.hil.nVal && !trGetN.ansig.nVal)
	//{
		//bOKEnable = false;
		//strErrMsg = XFERR_HILBERT_NO_OUTPUT;
		//
		//return false;//Sandy add 2008-9-28 fix OK still enable when this error message shows
	//}
	//
	//bOKEnable =  get_error_for_input_double_vector(trGetN.ix, strErrMsg);
	
	///Sandy 2008-10-20 add checking centralize function
	bOKEnable = _check_inputs(trGetN, strErrMsg);
	
	
	return false;

}

int hilbert_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void hilbert_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	//------ fisher 11/16/07 ADD_MAP_ID_TO_CHM
	if(is_use_origin_chm())
		trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_hilbert);
	
	//----Sandy 2008-10-20 add error checking in before execute
	string strErrMsg;
	if(!_check_inputs(trGetN, strErrMsg))
	{
		//if( (dwCntrl&LTXF_THEME_USED) && (dwCntrl&LTXF_FROM_GUI_MENU))
		if( (dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0)
		{
			nRet = XFEVT_PROCEED_WITH_DLG;
		}
		//else
		//{
			////warning_msg_box(nErr, false, 'E');
			//xf_warning_msg_box(strErrMsg, false, 'E');
			//nRet = XFEVT_ABORT;				
		//}
	}
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int hilbert_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
