#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	type_morlet,
	type_dgauss,
	type_mexhat,
};
#include <getnbox.h> // temp solution
#include <..\OriginLab\wavelet_utils.h>
//put your own support static functions here
#include <event_utils.h>
#include <o8dlg.h>

///////////////////////////////////////////////////////////////////////
//////// modification log
/// Max 8/27/08 v8.0931b POP_UP_DLG_ONLY_WHEN_DLG_IS_OPEN_FROM_MENU
/// Folger 11/06/08 v8.0966 ADD_PROPER_COMMENT_AND_PARAMETER_LABEL
/// ML 1/6/2009 QA70-12915 DONT_ADD_PARAM_LBL_IF_NOT_NEEDED
/// Folger 07/16/09 QA80-13957 CWT_FAILS_TO_PUT_NEW_DATA_ON_SOURCE_SHEET
/// Folger 10/23/09 QA81-14525-P3 CWT_UNDO_XF_RANGE_OUTPUT_WITH_NEW_COLUMNS
///////////////////////////////////////////////////////////////////////

bool _check_inputs(TreeNode& trGetN, string& strErrMsg)
{
	if(!get_error_for_input_double_vector(trGetN.ix1, strErrMsg) || !get_error_for_input_double_vector(trGetN.ix2, strErrMsg) )
	{
		strErrMsg = CER_NO_DATA;
		return false;
	}	
	vectorbase vScale, vData;
	TreeNode trX = trGetN.ix1;
	TreeNode trS = trGetN.ix2;
	if(trX.strVal =="" || trS.strVal == "")
	{
		strErrMsg = XFERR_WT_NO_DATA_INPUT;	
		return false;
	}
	else
	{
		vector vs;
		bool bRet = okxf_resolve_tree_get_data_into_vector(&trS, &vs);
		if(bRet)
		{
			vector vValidScales;
			//vValidScales = abs(vs);
			vValidScales = vs;
			vValidScales.Abs();
			
			if(vValidScales.GetSize()> 64)
				strErrMsg = XFERR_CWT_SCALE_TOO_LONG;			
			
			bool bIsSame;
			int nRet = ocmath_compare_data(vs.GetSize(), vValidScales, vs, &bIsSame);
			if(!bIsSame)
			{
				strErrMsg = XFERR_CWT_INVALID_SCALE;
				return false;
			}
	
						
		}
		else
		{
			strErrMsg = XFERR_CWT_INVALID_SCALE;	
			return false;
		}
	}
	
	
	
	
	int mUse = -1, rUse = -1;
	trGetN.mcoef.GetAttribute(STR_ATTRIB_DYNACONTROL_USE_CHECK, mUse);
	trGetN.rcoef.GetAttribute(STR_ATTRIB_DYNACONTROL_USE_CHECK, rUse);
	
	if(mUse == 0 && rUse == 0)
	{
		strErrMsg =  XFERR_NO_OUTPUT;
		return false;
	}
	
	//Nag_WavType nagType = g_nCwtWaveletType[trGetN.type.nVal];
	//if(nagType == Nag_DGauss)
	//{
		//trGetN.param.Show = true;			
		//trGetN.param.SetAttribute(STR_LABEL_ATTRIB, "Derivative Order");
		//trGetN.param.SetAttribute(STR_COMBO_ATTRIB, "1|2|3|4|5|6|7|8");
		//
		//if( 0 == lstrcmp(lpcszNodeName, "type"))
		//{
			//trGetN.param.nVal = 3;
		//}
	//}
	//else if(nagType == Nag_MexHat)
		//trGetN.param.Show = false;
	//else
	//{
		//trGetN.param.Show = true;			
		//trGetN.param.SetAttribute(STR_LABEL_ATTRIB, "Wave Number");
		//trGetN.param.SetAttribute(STR_COMBO_ATTRIB, "5|6|7|8|9|10|15|20");
		//if( 0 == lstrcmp(lpcszNodeName, "type"))
		//{
			//trGetN.param.nVal = 5;
		//}
	//}
	
	
	Nag_WavType nagType = g_nCwtWaveletType[trGetN.type.nVal];
	if(nagType == Nag_Morlet && (trGetN.param.nVal<5 || trGetN.param.nVal>20))
	{
		strErrMsg = INTOPTN_OUT_OF_RANGE;
		return false;
	}
	if(nagType == Nag_DGauss && (trGetN.param.nVal<0 || trGetN.param.nVal>8))
	{
		strErrMsg = INTOPTN_OUT_OF_RANGE;
		return false;
	}
	
	return true;
}

void cwt(const vector& ix1, const vector& ix2, const int& type, const int& param, Range& rcoef, MatrixObject& mcoef)
{
	waitCursor junk;
	//Nag_WavFilt filter;
	//Nag_WavType wavname = nCwtWaveletType[type];
	int n, ns;
	
	NagError fail;
	//INIT_FAIL
	fail.code = NE_NOERROR;
	fail.print = 0;
	
	n = ix1.GetSize();
	ns = ix2.GetSize();
	
	vector vValidScales;
	vValidScales = abs(ix2);
	
	bool bIsSame;
	int nRet = ocmath_compare_data(ns, vValidScales, ix2, &bIsSame);
	if(!bIsSame)
		XF_THROW(XFERR_CWT_INVALID_SCALE);
	
	matrix matCoef(ns, n);
	
	vector<int> nvScale;
	nvScale.SetSize(ns);
	nvScale=ix2;
	
	Nag_WavType nagType = g_nCwtWaveletType[type];
	if(nagType == Nag_Morlet && (param<5 || param>20))
		XF_THROW(INTOPTN_OUT_OF_RANGE);
	if(nagType == Nag_DGauss && (param<0 || param>8))
		XF_THROW(INTOPTN_OUT_OF_RANGE);
	
	/* 1D Continuous Wavelet Transform (CWT) */
	//nag_cwt_real(g_nCwtWaveletType[type], n, ix1, ns, nvScale, matCoef, &fail);
	nag_cwt_real(nagType, param, n, ix1, ns, nvScale, matCoef, &fail);
	if (fail.code != NE_NOERROR)
	{
	      XF_THROW_EX(XFERR_WT_FUNCTION_UNKNOWN_ERR, fail.code);
	      //XF_THROW_EX(CER_UNKNOWN_ERROR_EX, fail.code);
	}
	
	if(mcoef.IsValid())
	{
		if(!mcoef.SetSize(ns,n)) 
			XF_THROW(INTOPTN_OUT_OF_RANGE);
		matrix& mat = mcoef.GetDataObject();
		mat = matCoef;
		
		mcoef.SetXY(0, 1, n-1, ns);
	}
	
	//Jack 7/25/2008 CHANGE_COLUMN_COPY_TO_MATRIX_COPY_IMPROVE_SPEED
	if(rcoef.IsValid())
	{
		Worksheet wks;
		string strRange;
		int r1, c1, r2, c2;
	
		
		rcoef.GetRange(0, r1, c1, r2, c2, wks, &strRange);
	
		///------ Folger 07/16/09 QA80-13957 CWT_FAILS_TO_PUT_NEW_DATA_ON_SOURCE_SHEET
		//wks.SetSize(n, ns);
				
		//matCoef.CopyTo(wks,0,0,-1,-1,0,0,true, true);
		
		//rcoef.SetRange(0, wks, 0, 0, n-1, ns-1);
		///------ Folger 10/23/09 QA81-14525-P3 CWT_UNDO_XF_RANGE_OUTPUT_WITH_NEW_COLUMNS
		//wks.SetSize(n, c1 + ns);
		wks.SetSize(n, c1 + ns, OCD_UNDO);
		///------ End CWT_UNDO_XF_RANGE_OUTPUT_WITH_NEW_COLUMNS
		matCoef.CopyTo(wks, 0, 0, -1, -1, 0, c1, true, true);
		rcoef.SetRange(0, wks, 0, c1, n-1, c1 + ns - 1);
		///------ End CWT_FAILS_TO_PUT_NEW_DATA_ON_SOURCE_SHEET
	
		int ii=0;
		
		//------ Folger 11/06/08 v8.0966 ADD_PROPER_COMMENT_AND_PARAMETER_LABEL
		string		strComment;
		strComment.Format("%s of %s, %s", "cwt", get_input_data_range_string(ix1.GetSourceDataRange()), get_input_data_range_string(ix2.GetSourceDataRange()));
		
		Grid grid;
		grid.Attach(wks);
		vector<int>		vnTypes;
		grid.GetShowLabels(vnTypes);
		/// ML 1/6/2009 QA70-12915 DONT_ADD_PARAM_LBL_IF_NOT_NEEDED
		//vnTypes.Add(RCLT_PARAM);
		//grid.SetShowLabels(vnTypes);
		vector<uint>	vnIndices;
		if ( vnTypes.Find(MATREPL_TEST_EQUAL, RCLT_PARAM, vnIndices) <= 0 )
		{
			vnTypes.Add(RCLT_PARAM);
			grid.SetShowLabels(vnTypes);
		}
		/// end DONT_ADD_PARAM_LBL_IF_NOT_NEEDED
		//------ End ADD_PROPER_COMMENT_AND_PARAMETER_LABEL
		
		foreach(Column col in wks.Columns)
		{
			///------ Folger 07/16/09 QA80-13957 CWT_FAILS_TO_PUT_NEW_DATA_ON_SOURCE_SHEET
			if ( col.GetIndex() < c1 )
				continue;
			///------ End CWT_FAILS_TO_PUT_NEW_DATA_ON_SOURCE_SHEET
			//------ Folger 11/06/08 v8.0966 ADD_PROPER_COMMENT_AND_PARAMETER_LABEL
			//col.SetLabel((string)((int)ix2[ii]));
			col.SetParameter((string)((int)ix2[ii]));
			col.SetComments(strComment);
			//------ End ADD_PROPER_COMMENT_AND_PARAMETER_LABEL
			ii++;
		}
	}
	// End CHANGE_COLUMN_COPY_TO_MATRIX_COPY_IMPROVE_SPEED
	
	/*
	if(rcoef.IsValid())
	{
		Worksheet wks;
		string strRange;
		int r1, c1, r2, c2;
		rcoef.GetRange(0, r1, c1, r2, c2, wks, &strRange);
		//wks.SetSize(n, ns);
		//matCoef.CopyTo(wks);
		//rcoef.SetRange(0, wks, 0, 0, n-1, ns-1);
		for(int ii=0; ii<ns; ii++)
		{
			vector vRow;
			matCoef.GetRow(vRow, ii);
			//int nCol = wks.AddCol();
			//rcoef.Add((string)(s[ii]), wks, 0, nCol, -1, nCol);
			rcoef.SetColumnData(vRow, true, ii);
			
			Column col(wks, c1+ii);
			col.SetLabel((string)((int)ix2[ii]));
			
		}
			
	}
	
	*/	
	
	
}

//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 cwt_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return cwt_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
	
	
	//int n1 = Nag_DGauss;
	//int n2 = Nag_MexHat;
	
	
	
	Nag_WavType nagType = g_nCwtWaveletType[trGetN.type.nVal];
	if(nagType == Nag_DGauss)
	{
		trGetN.param.Show = true;			
		trGetN.param.SetAttribute(STR_LABEL_ATTRIB, _L("Derivative Order"));
		trGetN.param.SetAttribute(STR_COMBO_ATTRIB, "1|2|3|4|5|6|7|8");
		
		if( 0 == lstrcmp(lpcszNodeName, "type"))
		{
			trGetN.param.nVal = 3;
		}
	}
	else if(nagType == Nag_MexHat)
		trGetN.param.Show = false;
	else
	{
		trGetN.param.Show = true;			
		trGetN.param.SetAttribute(STR_LABEL_ATTRIB, _L("Wave Number"));
		trGetN.param.SetAttribute(STR_COMBO_ATTRIB, "|5|6|7|8|9|10|15|20");
		if( 0 == lstrcmp(lpcszNodeName, "type"))
		{
			trGetN.param.nVal = 5;
		}
	}
	
	 bOKEnable = _check_inputs(trGetN,  strErrMsg);
	 //if(!bOKEnable)
	 	//return false;	
	
	
	return true;

}

int cwt_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return true;
}
//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 cwt_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_cwt);
	
	/// Max 8/27/08 v8.0931b POP_UP_DLG_ONLY_WHEN_DLG_IS_OPEN_FROM_MENU
	// dialog should be popped up only when it is called from menu	
	/////Sandy 2008-8-25 add checking error when no dlg
	//if(nGetNDialog == 0)
	if(0 == nGetNDialog && (dwCntrl&LTXF_THEME_USED) && (dwCntrl&LTXF_FROM_GUI_MENU) )
	/// END POP_UP_DLG_ONLY_WHEN_DLG_IS_OPEN_FROM_MENU
	{
		string strErrMsg;
		if(!_check_inputs(trGetN,  strErrMsg))
			nRet = XFEVT_PROCEED_WITH_DLG;
	}
	
	//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
}
//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 cwt_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
