#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	type_haar,
	type_db2,
	type_db3,
	type_db4,
	type_db5,
	type_db6,
	type_db7,
	type_db8,
	type_db9,
	type_db10,
	type_b11,
	type_b13,
	type_b15,
	type_b22,
	type_b24,
	type_b26,
	type_b28,
	type_b31,
	type_b33,
	type_b35,
	type_b37,
};
enum{
	ext_periodic,
	ext_pad0,
};
#include <GetNbox.h>
#include <..\OriginLab\wavelet_utils.h>
#include <event_utils.h>
#include <o8dlg.h>
//put your own support static functions here
#include <ReportTree.h>

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

//put your own support static functions here


static string _create_levels_list(int nLevel)
{

	string strList;
	strList = (string)(1);
	for(int ii = 2; ii <=nLevel; ii++)
	{
		strList += "|"+ (string)(ii); 
	}
	
	return strList;
}

static bool _output_coeff_data_to_report_data(ReportData& outData, vector& vC, vector& vL, string strTableLabel)
{
	int nIDy = IDST_FIT_Y;
	int nIDx = IDST_FIT_X;
	outData.ID = IDST_RESULT_CURVES;
	
	ReportTable rtCoeff;
	/*
	string strTableName;
	int _ID_DATA_TABLE = 200;
	strTableName.Format(_L("Multiple_Level_DWT"));
	rtCoeff = outData.CreateTable(strTableName, strTableName, _ID_DATA_TABLE);
	*/
	string strTableTagName/*, strTableLabel*/;
	int _ID_DATA_TABLE = 200;
	strTableTagName.Format("Multiple_Level_DWT");
	//strTableLabel.Format(_L("Multiple Level DWT"));
	rtCoeff = outData.CreateTable(strTableTagName, strTableLabel, _ID_DATA_TABLE);

	double dCoeffLen;
	vL.Sum(dCoeffLen);
	int nLenOfAppr = vL[0];
	
	//Add Approximation Coefficient
	vector vA;
	int iOffset; 
	vC.GetSubVector(vA, 0, nLenOfAppr-1);
	iOffset = nLenOfAppr;
	
	int nLevel = vL.GetSize()-1;
	/*
	string strA = _L("Approxi") + (string)(nLevel);
	rtCoeff.AddColumn(vA, strA, nIDy,  strA);
	*/
	string strA = _LE("Approxi");
	string strSNameA = strA + (string)(nLevel);
	string strLNameA = GetLocalized(strA) + (string)(nLevel);
	rtCoeff.AddColumn(vA, strSNameA, nIDy, strLNameA);
	
	for(int ii = 1; ii<=nLevel; ii++)
	{
		vector vD;
		if( 0 != vC.GetSubVector(vD, iOffset, iOffset+vL[ii]-1))
			return false;
		
		iOffset = iOffset+vL[ii];
		
		//Add Detail Coefficient
		/*
		string strD = _L("Detail") + (string)(nLevel-ii+1);
		rtCoeff.AddColumn(vD, strD, nIDy+ii, strD);
		*/
		string strD = _LE("Detail");
		string strSNameD = strD + (string)(nLevel-ii+1);
		string strLNameD = GetLocalized(strD) + (string)(nLevel-ii+1);		
		rtCoeff.AddColumn(vD, strSNameD, nIDy+ii, strLNameD);
	}
	
	return true;
}

//------ Folger 07/28/08 BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS
static	string	_get_output_range_comments(const vector& ix, int nLevel, int nType)
{
	string strComments;
	strComments.Format("%d level(s) %s mdwt of %s", nLevel, get_wavelet_type_string(nType), get_input_data_range_string(ix.GetSourceDataRange()));
	return strComments;
}
//------ End BETTER_OPREATION_OUTPUT_COLUMN_COMMENTS


void mdwt(const vector& ix, const int& type, const int& ext, const int& level, ReportData& rd)
{
	waitCursor junk;
	//wavelet type
	//vector<Nag_WavType> vWavType = {Nag_Haar, Nag_DB4, Nag_DB6, Nag_DB8, Nag_DB10, Nag_DB12, Nag_DB14, Nag_DB16, Nag_DB18, Nag_DB20, Nag_Bior1_1, Nag_Bior1_3, Nag_Bior1_5, Nag_Bior2_2, Nag_Bior2_4, Nag_Bior2_6, Nag_Bior2_8, Nag_Bior3_1, Nag_Bior3_3, Nag_Bior3_5};
	
	//vector<Nag_WavType> vWavType= {
						    //Nag_Haar,
						    //Nag_DB2,
						    //Nag_DB3,
						    //Nag_DB4,
						    //Nag_DB5,
						    //Nag_DB6,
						    //Nag_DB7,
						    //Nag_DB8,
						    //Nag_DB9,
						    //Nag_DB10,
						    //Nag_Bior1_1,
						    //Nag_Bior1_3,
						    //Nag_Bior1_5,
						    //Nag_Bior2_2,
						    //Nag_Bior2_4,
						    //Nag_Bior2_6,
						    //Nag_Bior2_8,
						    //Nag_Bior3_1,
						    //Nag_Bior3_3,
						    //Nag_Bior3_5,
						    //Nag_Bior3_7
						  //} ;
	Nag_WavFilt filter;
	if(ext <0 || ext > 1 )
	{
		nag_free_wavfilter(&filter);
		XF_THROW(XFERR_WT_EXTEND_MODE_INVALID);
	}
	
	//Nag_WavType wavname = vWavType[t];
	Nag_WavModeType mode = g_nWaveModes[ext];
	/* Read end extension mode */ 
	//vector<string> vWaveMode = {"Periodic", "Zero-padded"};
	
	
	
	int i, n, nc, nLevel;
	//compute the max level
	int nSignalLen=ix.GetSize();
	
	//nLevel=min(7,(int)(log10(nSignalLen-1)/log10(2)));
	nLevel = (int)(log10(nSignalLen)/log10(2));
	
	///Sandy 2006-11-29 when using perodic mode, should not decompose to the lowest level.
	if(mode == Nag_PerWavExt)
		nLevel -=1;
	
	if(level>nLevel)
		XF_THROW(CER_INPUT_OPTION_OUT_OF_RANGE);
	nLevel = min(level, nLevel);
	
	n = get_enough_length_to_be_decompose(nSignalLen, nLevel);
	//n=pow(2,nLevel);
	//if(nSignalLen>n)
	//{
		//n=nSignalLen/128+(nSignalLen%128!=0?1:0);
		//n=n*128;
	//}
	vector y;
	y = ix;
	y.SetSize(n);
	//double maxerr;
	//NagError fail;
	////INIT_FAIL
	//fail.code = NE_NOERROR;
	//fail.print = 0;
	
	/* Initialise filter coefficients */
	if(!create_wavelet_filter(g_nWaveletType[type], filter))
		XF_THROW(XFERR_WT_FAILED_TO_CREATE_FILTER);
	
	
	vector vC,vL;	
	if(!multi_scale_dwt(nLevel,mode,y,filter,vC,vL))
	{
		nag_free_wavfilter(&filter);
		XF_THROW(XFERR_WT_MULTI_DWT_FAILED);
	}
	nag_free_wavfilter(&filter);
	
	_output_coeff_data_to_report_data(rd, vC, vL, _get_output_range_comments(ix, level, type));
	
	
}

//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 mdwt_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return mdwt_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	///Kyle 09/24/08 SET_NO_NEED_TO_LOCALIZE
	if( GETNE_ON_INIT == nEventID )
	{
		trGetN.type.SetAttribute( STR_OCNTRL_OPTNS, OCNTRLPARAM1_NOT_LOCALIZED);
	}
	///End SET_NO_NEED_TO_LOCALIZE
	
	if(!get_error_for_input_double_vector(trGetN.ix, strErrMsg))
	{
		strErrMsg = CER_NO_DATA;
		bOKEnable = false;
	}
	
	TreeNode trX = trGetN.ix;
	vector vx;
	if(okxf_resolve_tree_get_data_into_vector(&trX, &vx))
	{
		int nSize = vx.GetSize();
	
		//int nLevel=min(7,(int)(log10(nSize)/log10(2)));
		int nLevel=(int)(log10(nSize)/log10(2));
		
		if(trGetN.ext.nVal == 0)
			nLevel -=1;
	
		if(!lstrcmpi(lpcszNodeName,  "ix") || trGetN.level.nVal>nLevel || 0 >= trGetN.level.nVal )
		{
			trGetN.level.nVal = nLevel;
		}			
		
		string strAttr = _create_levels_list(nLevel);
		trGetN.level.SetAttribute(STR_COMBO_ATTRIB, strAttr);
	}
	
	
	
	
	return true;

}

int mdwt_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 mdwt_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_mdwt);
	
	if ( (dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0 )
	{
		int nSize;
		TreeNode trInput= trGetN.yi;
		XYRange xyi;	
		string strErrMsg;
		if ( true != get_error_for_input_xyrange(trInput, strErrMsg, nSize, xyi) )
			nRet = XFEVT_PROCEED_WITH_DLG;
		
		if(0 >= trGetN.level.nVal)
			nRet = XFEVT_PROCEED_WITH_DLG; 
	}
	
}
//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 mdwt_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
