#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	cond_eq,
	cond_lt,
	cond_le,
	cond_gt,
	cond_ge,
	cond_ne,
};
enum{
	lookin_active_object,
	lookin_active_sheet,
	lookin_active_book,
	lookin_all_in_active_folder,
	lookin_recursive_in_active_folder,
	lookin_open_in_active_folder,
	lookin_all_in_project,
	lookin_specified,
};
#include <event_utils.h>
//put additional include files here

/*
/// Iris 7/14/2009 QA80-13941 SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
/// Iris 7/29/2009 WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
/// Sophy 8/12/2009 QA80-13941-P4 ALLOW_INPUT_MATRIX_WITH_ALL_MISSING_VALUES
/// Sophy 8/12/2009 QA80-13941-P5 LESS_THAN_GREATER_THAN_DONT_SUPPORT_TOLERANCE
/// Sophy 8/12/2009 QA80-13941-P6 OUTPUT_TO_NEW_SHOULD_ONLY_AVAILABLE_WHEN_INPUT_IS_SINGLE_MATRIXOBJECT
/// Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
/// Sophy 8/14/2009 QA80-13941-P8 ACTIVE_MATRIXOBJECT_AS_INPUT_SHOULD_NOT_BE_EDITABLE
/// Sophy 8/14/2009 QA80-13941-P9 CHECK_INPUT_DATA_TO_VALIDATE_USER_CHANGES
/// Sophy 8/21/2009 QA80-13941-P7 CHECK_ERROR_CODE_AS_FIND_REPLACE_RESULT
*/

//put your own support static functions here
enum{
	REPLACE_CONDITION_EQUAL = 0,
	REPLACE_CONDITION_LESSTHAN,
	REPLACE_CONDITION_LESSTHAN_EQUAL,
	REPLACE_CONDITION_GREATER,
	REPLACE_CONDITION_GREATER_EQUAL,
	REPLACE_CONDITION_LESSTHAN_GREATER,
};

/// Iris 7/14/2009 QA80-13941 SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
/// Iris 7/29/2009 WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
/*
static int _get_active_page_type()
{
	Page pg = Project.Pages();
	if(pg)
		return pg.GetType();
	return EXIST_NONE;
}
*/
///end WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE

static int _get_lookin_options(int nSel)
{
	if( lookin_specified == nSel )
		return OPTION_SPECIFIED;	
	
	/// Iris 7/29/2009 WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
	//return get_lookin_options(nSel, _get_active_page_type());
	return get_lookin_options(nSel, EXIST_MATRIX);
	///end WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
}

///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
static bool _replace_within_one_range(DataRange& dr, double find, double replace, uint nOption, double abs_error)
{
	//since there is always one subrange(one MatrixObject) in dr, so can use 0 as subrange index here
	///Sophy 8/21/2009 QA80-13941-P7 CHECK_ERROR_CODE_AS_FIND_REPLACE_RESULT
	//return dr.Replace(find, replace, nOption, 0, abs_error);
	//the return value is the number of data replaced, but not TRUE or FALSE
	int nErr = 0;
	dr.Replace(find, replace, nOption, 0, abs_error, FALSE, &nErr);
	return (0 == nErr);
	///end CHECK_ERROR_CODE_AS_FIND_REPLACE_RESULT
}
///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
static bool _replace_with_matrixbase(matrixbase& mat, double find, double replace, int cond, uint nOption, double abs_error)
{
	bool bRet = false;
	
	// copy from old code even I did not known why check cond to decide input 
	if(cond == REPLACE_CONDITION_EQUAL || cond == REPLACE_CONDITION_LESSTHAN_EQUAL 
			 || cond == REPLACE_CONDITION_GREATER_EQUAL || cond == REPLACE_CONDITION_LESSTHAN_GREATER)
	{
		///Add overload of matrixbase::replace()
		bRet = mat.Replace( find, replace, nOption, abs_error);		
	}
	else
	{
		bRet = mat.Replace( find, replace, nOption );
	}
	return bRet;
}

static bool _replace_all(MatrixObject& om, int lookin, double find, double replace, int cond, uint nOption, double abs_error)
{
	int nLookInOption = _get_lookin_options(lookin);
	string strRngStr;///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
	if( OPTION_SPECIFIED == nLookInOption )
	{
		///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
		//matrixbase& mat = om.GetDataObject();
		//return _replace_with_matrixbase(mat, find, replace, cond, nOption, abs_error);
		DataRange dr;
		om.GetRangeString(strRngStr);
		dr.Add("M", strRngStr);
		bool bRet = _replace_within_one_range(dr, find, replace, nOption, abs_error);
		if ( bRet )
		{
			MatrixLayer ml;
			om.GetParent(ml);
			if ( ml )
			{
				Page pg = ml.GetPage();
				pg.Refresh();
			}
		}
		return bRet;
		///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
	}
	else if( OPTION_ACTIVE_MATRIX_OBJECT == nLookInOption )
	{
		MatrixLayer ml = Project.ActiveLayer();
		if(ml)
		{
			MatrixObject mo = ml.MatrixObjects();
			///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
			//matrixbase& mat = mo.GetDataObject();
			//return _replace_with_matrixbase(mat, find, replace, cond, nOption, abs_error);
			DataRange dr;
			mo.GetRangeString(strRngStr);
			dr.Add("M", strRngStr);
			bool bRet = _replace_within_one_range(dr, find, replace, nOption, abs_error);
			if ( bRet )
			{
				Page pg = ml.GetPage();
				pg.Refresh();
			}
			return bRet;
			///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
		}
	}
	else if( OPTION_ACTIVE_SHEET == nLookInOption )
	{
		MatrixLayer ml = Project.ActiveLayer();
		if(ml)
		{
			foreach(MatrixObject mo in ml.MatrixObjects)
			{
				///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
				//matrixbase& mat = mo.GetDataObject();
				//_replace_with_matrixbase(mat, find, replace, cond, nOption, abs_error);
				DataRange dr;
				mo.GetRangeString(strRngStr);
				dr.Add("M", strRngStr);
				_replace_within_one_range(dr, find, replace, nOption, abs_error);
				///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
			}
			///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
			Page pg = ml.GetPage();
			pg.Refresh();
			///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
			return true;
		}
	}
	else
	{
		vector<string> vsBookNames;
		/// Iris 7/29/2009 WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
		//get_folder_pages_name(vsBookNames, nLookInOption, 0, NULL, NULL, _get_active_page_type());
		get_folder_pages_name(vsBookNames, nLookInOption, 0, NULL, NULL, EXIST_MATRIX);
		///end WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
		if( vsBookNames.GetSize() == 0 )
			return false;
	
		for(int index = 0; index < vsBookNames.GetSize(); index++ )
		{
			Page pg(vsBookNames[index]);			
			
			foreach(Layer lay in pg.Layers)
			{
				MatrixLayer ml(lay);
				
				foreach(MatrixObject mo in ml.MatrixObjects)
				{
					///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
					//matrixbase& mat = mo.GetDataObject();
					//_replace_with_matrixbase(mat, find, replace, cond, nOption, abs_error);		
					DataRange dr;
					mo.GetRangeString(strRngStr);
					dr.Add("M", strRngStr);
					_replace_within_one_range(dr, find, replace, nOption, abs_error);
					///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
				}
			}
			pg.Refresh(); ///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
		}		
		return true;
	}
	
	return false;
}
///end SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF


void mreplace(MatrixObject& im, const int& cond, const double& find, const double& replace, const double& abs_error, const int& use_abs, const int& keep_sign, const int& set_missing, const int& lookin, MatrixObject& om)
{
	
	if(!matobj_copy(om,im))
	{
		XF_THROW(XFERR_OUTPUT_MATRIX_NOT_AVALID);
	}	
	
	matrixbase& mat = om.GetDataObject();
	
	uint nOption = 0;
	switch(cond)
	{
	case REPLACE_CONDITION_EQUAL:
		nOption = MATREPL_TEST_EQUAL;
		break;
	case REPLACE_CONDITION_LESSTHAN:
		nOption = MATREPL_TEST_LESSTHAN;
		break;
	case REPLACE_CONDITION_LESSTHAN_EQUAL:
		nOption = MATREPL_TEST_LESSTHAN|MATREPL_TEST_EQUAL;
		break;
	case REPLACE_CONDITION_GREATER:
		nOption = MATREPL_TEST_GREATER;
		break;
	case REPLACE_CONDITION_GREATER_EQUAL:
		nOption = MATREPL_TEST_GREATER|MATREPL_TEST_EQUAL;
		break;
	case REPLACE_CONDITION_LESSTHAN_GREATER:
		nOption = MATREPL_TEST_GREATER|MATREPL_TEST_LESSTHAN;
		break;
	default:
		XF_THROW(XFERR_INTOPTN_OUT_OF_RANGE);
		break;
	}
	
	if(use_abs)
		nOption |= MATREPL_USE_ABSOLUTE_VALUE_IN_TEST;
	
	if(keep_sign)
		nOption |= MATREPL_KEEP_ORIGINAL_SIGN_WHEN_TEST_RESULT_IS_TRUE;
	
	if(set_missing)
		nOption |= MATREPL_SET_TO_MISSING_VALUE_WHEN_TEST_RESULT_IS_FALSE;
	
	bool bRet = false;
	if(abs_error < 0)
		XF_WARN(XFWARN_ABSOLUTE_ERROR_IS_MINUS);
	
	/// Iris 7/14/2009 QA80-13941 SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
	/*
	if(cond == REPLACE_CONDITION_EQUAL || cond == REPLACE_CONDITION_LESSTHAN_EQUAL 
			 || cond == REPLACE_CONDITION_GREATER_EQUAL || cond == REPLACE_CONDITION_LESSTHAN_GREATER)
	{
		///Add overload of matrixbase::replace()
		bRet = mat.Replace( find, replace, nOption , abs_error);		
	}
	else
	{
		bRet = mat.Replace( find, replace, nOption );
	}
	*/
	bRet = _replace_all(om, lookin, find, replace, cond, nOption, abs_error);
	///end SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
	
	
	if (!bRet)	
	{
		XF_THROW(CER_MATRIX_FAILED_IN_REPLACE);
	}
}

//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 mreplace_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return mreplace_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.cond.SetAttribute(STR_OCNTRL_OPTNS, OCNTRLPARAM1_NOT_LOCALIZED);
	}
	///End SET_NO_NEED_TO_LOCALIZE
	
	/// Iris 7/14/2009 QA80-13941 SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
	// do not know why always set im control disable but this control very useful and for now will not recommend customer use this xf with dialog.
	//trGetN.im.Enable = false; 
	///end SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
	
	/// Iris 7/14/2009 QA80-13941 SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
	///Sophy 8/12/2009 QA80-13941-P6 OUTPUT_TO_NEW_SHOULD_ONLY_AVAILABLE_WHEN_INPUT_IS_SINGLE_MATRIXOBJECT
	//trGetN.im.Show = (lookin_specified == trGetN.lookin.nVal); 
	//trGetN.om.Show = (lookin_specified == trGetN.lookin.nVal);
	bool bShow = (lookin_specified == trGetN.lookin.nVal || lookin_active_object == trGetN.lookin.nVal);
	trGetN.im.Show = bShow; 
	trGetN.om.Show = bShow;
	if ( !bShow )
		trGetN.om.strVal = STR_INPUT;
	
	///end OUTPUT_TO_NEW_SHOULD_ONLY_AVAILABLE_WHEN_INPUT_IS_SINGLE_MATRIXOBJECT
	///end SUPPORT_MORE_OPTIONS_FOR_WREPLACE_AND_MREPLACE_XF
	///Sophy 8/14/2009 QA80-13941-P8 ACTIVE_MATRIXOBJECT_AS_INPUT_SHOULD_NOT_BE_EDITABLE
	bool bActiveObject = lookin_active_object == trGetN.lookin.nVal;
	trGetN.im.Enable = !bActiveObject;
	if ( bActiveObject )
	{
		MatrixLayer ml = Project.ActiveLayer();
		if ( ml )
		{
			MatrixObject moActive = ml.MatrixObjects();
			string strRngStr;
			moActive.GetRangeString(strRngStr);
			trGetN.im.strVal = strRngStr;
		}
	}
	///end ACTIVE_MATRIXOBJECT_AS_INPUT_SHOULD_NOT_BE_EDITABLE
	
	///Echo 11/1/06 CHECK_NUMERIC_MATRIX
	int nErr = check_numeric_matrix(trGetN.im.strVal);	
	nErr = CER_NO_DATA ? CER_NO_ERROR : nErr;///Sophy 8/12/2009 QA80-13941-P4 ALLOW_INPUT_MATRIX_WITH_ALL_MISSING_VALUES
	
	///Sophy 8/14/2009 QA80-13941-P9 CHECK_INPUT_DATA_TO_VALIDATE_USER_CHANGES
	if ( nErr == CER_NO_ERROR && bShow )
	{
		MatrixObject mo;
		okxf_resolve_string_get_origin_object(trGetN.im.strVal, &mo);
		if ( !mo )
			nErr = CER_INVALID_MATOBJ;
	}
	///end CHECK_INPUT_DATA_TO_VALIDATE_USER_CHANGES
	
	if (nErr != CER_NO_ERROR)		
	{
		strErrMsg = nErr;
		bOKEnable = false;
	}
	///END CHECK_NUMERIC_MATRIX
	if(!lstrcmpi(lpcszNodeName, "cond") || GETNE_ON_INIT == nEventID ) //GETNE_ON_INIT == nEventID when from theme
	{
		///Sophy 8/12/2009 QA80-13941-P5 LESS_THAN_GREATER_THAN_DONT_SUPPORT_TOLERANCE
		//if(trGetN.cond.nVal == REPLACE_CONDITION_EQUAL || trGetN.cond.nVal == REPLACE_CONDITION_LESSTHAN_EQUAL 
			 //|| trGetN.cond.nVal == REPLACE_CONDITION_GREATER_EQUAL || trGetN.cond.nVal == REPLACE_CONDITION_LESSTHAN_GREATER)
		if(trGetN.cond.nVal == REPLACE_CONDITION_EQUAL || trGetN.cond.nVal == REPLACE_CONDITION_LESSTHAN_EQUAL 
			 || trGetN.cond.nVal == REPLACE_CONDITION_GREATER_EQUAL)
		///end LESS_THAN_GREATER_THAN_DONT_SUPPORT_TOLERANCE
	    {
	    	//trGetN.tolerance.Show = true; ///Echo 11/1/06 UNSHOWN_CHANGED_DIALOGUE_SIZE
	    	///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
	    	//trGetN.abs_error.Enable = true;
	    	trGetN.abs_error.Show = true;
	    	///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
	    }
	    else
	    {
	    	//trGetN.tolerance.Show = false; ///Echo 11/1/06 UNSHOWN_CHANGED_DIALOGUE_SIZE
	    	///Sophy 8/14/2009 QA80-13941-P7 REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
	    	//trGetN.abs_error.Enable = false;
	    	trGetN.abs_error.Show = false; //Sophy, when not allow to use tolerance, should hide it, or user may be confused.
	    	///end REPLACE_MATRIX_DATA_WITH_DATARANGE_TO_KEEP_CONSISTENT_WITH_WREPLACE
	    }
	    
	    return true;
	}
	return false;

}

int mreplace_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 mreplace_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	/// Iris 7/29/2009 WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
	/*
	/// Iris 7/16/2009 CHECK_ERROR_ON_ACRIVE_IF_PAGE_VALID_AND_IF_VALID_WORKSHEETPAGE
	Page pg = Project.Pages();
	if( !pg || EXIST_MATRIX != pg.GetType())
	{
		warning_msg_box(CER_NO_MATRIX, false);
		nRet = XFEVT_ABORT;
		return;
	}
	///end CHECK_ERROR_ON_ACRIVE_IF_PAGE_VALID_AND_IF_VALID_WORKSHEETPAGE
	*/	
	MatrixObject mo;
	okxf_resolve_string_get_origin_object(trGetN.im.strVal, &mo);
	if( !mo )
	{
		warning_msg_box(CER_INVALID_MATOBJ, false);
		nRet = XFEVT_ABORT;
	}
	///end WREPLACE_AND_MREPLACE_XF_FIX_ALWAYS_ASSUME_REPLACE_RANGE_IS_ACTIVE_PAGE
	
}
//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 mreplace_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
