#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,
};
#include <..\OriginLab\wavelet_utils.h>
//put your own support static functions here
//enum {
	//CREATE_WAVELET_FILTER_ERROR = XF_LOCAL_ERR_BEGIN,
	//ERROR_SIZE_OF_INPUT,
//};



void idwt2(const MatrixObject& ca, const MatrixObject& ch, const MatrixObject& cv, const MatrixObject& cd, const int& type, MatrixObject& om)
{
	waitCursor junk;
	//	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;
	//Nag_WavType wavname = vWavType[type];
	int  m, n,mc, nc;
	//NagError fail;
	////INIT_FAIL
	//fail.code = NE_NOERROR;
	//fail.print = 0;
	//
	///* Initialise filter coefficients */
	//nag_wavfilter(wavname, &filter, &fail);
	//if (fail.code != NE_NOERROR)
	//{
		//printf(fail.message);
	//}
	
	if(!create_wavelet_filter(g_nWaveletType[type], filter))
		XF_THROW(XFERR_WT_FAILED_TO_CREATE_FILTER);
	
	nc = ca.GetNumCols();
	mc = ca.GetNumRows();
	if( (ch.GetNumCols()!=nc)||(ch.GetNumRows()!=mc)
		||(cv.GetNumCols()!=nc)||(cv.GetNumRows()!=mc)
		||(cd.GetNumCols()!=nc)||(cd.GetNumRows()!=mc) )
	{
		nag_free_wavfilter(&filter);
		XF_THROW(XFERR_WT_COEFFS_NOT_MATCH);
		//printf("error input: ca,ch,cd,cv with different size!");
		//goto END;
	}
	
	
	/* extension mode is Periodic*/
	Nag_WavModeType mode = Nag_PerWavExt;
	
	///Sandy 2006-9-22 No need to check 
	//if(mc&1||nc&1)
	//{
		//nag_free_wavfilter(&filter);
		//XF_THROW(XFERR_WT_COEFFS_NOT_MATCH);
		////printf("error input: ca,ch,cd,cv must have even Rows and Cols!");		
		////goto END;	
	//}
	
	m=mc*2;
	n=nc*2;
	
	//matrix ca(mc,nc), ch(mc,nc), cv(mc,nc), cd(mc,nc);
	om.SetSize(m,n);
	om.SetXY(1, 1, n, m);
	
	matrixbase &mbca=ca.GetDataObject();
	matrixbase &mbch=ch.GetDataObject();
	matrixbase &mbcv=cv.GetDataObject();
	matrixbase &mbcd=cd.GetDataObject();
	
	matrix matca=mbca;
	matrix match=mbch;
	matrix matcv=mbcv;
	matrix matcd=mbcd;
	
	matrix &mbdst=om.GetDataObject();
	vector vb(n*m);
	//printf("wavmode = Periodic,mc = %ld, nc = %ld, m = %ld, n = %ld\n", mc, nc, m, n);
	
	matrix matdst = mbdst;
	
	/* 2D Inverse Discrete Wavelet Transform (IDWT2) (one level)*/
	NagError fail;
	nag_idwt2(mode,mc,nc,matca,match,matcv,matcd,&filter,vb,&fail);
	if (fail.code != NE_NOERROR)
	{
		nag_free_wavfilter(&filter);
		XF_THROW_EX(XFERR_WT_FUNCTION_UNKNOWN_ERR, fail.code);
	  //printf("Error from nag_idwt2.\n%s\n", fail.message);
	  //goto END;
	}
	mbdst.SetByVector(vb);
	
	//END:
	
	nag_free_wavfilter(&filter);
	
	
}

//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 idwt2_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return idwt2_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
	
	MatrixObject mca, mch, mcv, mcd;
	if(!okxf_resolve_string_get_origin_object(trGetN.ca.strVal, &mca) || !mca.IsValid() 
		|| !okxf_resolve_string_get_origin_object(trGetN.ch.strVal, &mch) || !mch.IsValid() 
		|| !okxf_resolve_string_get_origin_object(trGetN.cv.strVal, &mcv) || !mcv.IsValid() 
		|| !okxf_resolve_string_get_origin_object(trGetN.cd.strVal, &mcd) || !mcd.IsValid() )	
	{
		strErrMsg = XFERR_INVALID_MATOBJ;
		bOKEnable = false;
		return false;
	}
	///Sophy 6/24/2010 ORG-322-P1 BETTER_ERR_MSG_INFORM_CVT_IMAGE_TO_DATA
	if ( !mca.HasData(false)
		|| !mch.HasData(false)
		|| !mcv.HasData(false)
		|| !mcd.HasData(false) )
	{
		strErrMsg = CER_NEED_CVT_TO_DATA;
		bOKEnable = false;
		return false;
	}
	///end BETTER_ERR_MSG_INFORM_CVT_IMAGE_TO_DATA
	
	
	int nCols = mca.GetNumCols();
	int nRows = mca.GetNumRows();
	
	if(mch.GetNumCols() != nCols || mcv.GetNumCols() != nCols || mcd.GetNumCols() != nCols
		||mch.GetNumRows() != nRows || mcv.GetNumRows() != nRows || mcd.GetNumRows() != nRows)
	{
		strErrMsg = XFERR_WT_MATRIX_SIZE_NOT_MATCH;
		bOKEnable = false;
		return false;		
	}
	return true;

}

int idwt2_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 idwt2_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	///Sophy 6/24/2010 ORG-322-P1 BETTER_ERR_MSG_INFORM_CVT_IMAGE_TO_DATA
	MatrixObject mca, mch, mcv, mcd;
	if(!okxf_resolve_string_get_origin_object(trGetN.ca.strVal, &mca) || !mca.IsValid() 
		|| !okxf_resolve_string_get_origin_object(trGetN.ch.strVal, &mch) || !mch.IsValid() 
		|| !okxf_resolve_string_get_origin_object(trGetN.cv.strVal, &mcv) || !mcv.IsValid() 
		|| !okxf_resolve_string_get_origin_object(trGetN.cd.strVal, &mcd) || !mcd.IsValid() )
	{
		nRet = XFEVT_PROCEED_WITH_DLG;
	}
	///end BETTER_ERR_MSG_INFORM_CVT_IMAGE_TO_DATA
	
}
//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 idwt2_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
