#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	cond_sd,
	cond_gt,
	cond_ge,
	cond_lt,
	cond_le,
	cond_eq,
};
#include <event_utils.h>
#include <..\originlab\XFunctionEx.h>
/// Jake 04/25/07 CREATE_THIS_XF_TO_MASK_THE_DATA_EACH_CELL
/// Jake 05/08/07 DEGUB_FOR_COL_AND_ROW_SELECTION
/// Max 1/28/08 ADD_UNMASK
/// EJP 2009-10-21 QA81-14513 ADD_CONDITION_TO_WCELLMASK_XF
///--- CPY 10/22/09 QA70-14513-P1 CHKBOX_TO_REPLACE_OR_KEEP
///--- CPY 10/22/09 QA70-14513-P2 SHOULDNOT_CARE_IF_Y, before this, it will not work if X col
///--- CPY 10/22/09 QA70-14513-P3 NO_WKS_SEL_SHOULD_WORK_ON_WHOLE_SHEET
///--- CPY 10/22/09 QA70-14513-P4 NEED_TO_SUPPORT_EUAL_TO_AS_WELL
/// Kenny 11/04/2009 QA81-14513-P2 XF_COL_MASK_IMPROVE_ERROR_CHECKING
 
/// EJP 2009-10-21 QA81-14513 ADD_CONDITION_TO_WCELLMASK_XF
void _update_cond_dependent_ctrls(TreeNode& trGetN)
{
	if(trGetN.cond.Enable)
	{
		trGetN.nsd.Show = (trGetN.cond.nVal == cond_sd);
		trGetN.val.Show = (trGetN.cond.nVal != cond_sd);
	}
	else
		trGetN.nsd.Show = trGetN.val.Show = false;
	
	
	trGetN.abs.Show = trGetN.val.Show;///--- CPY 10/22/09 QA70-14513-P4 NEED_TO_SUPPORT_EUAL_TO_AS_WELL

}
///--- CPY 10/22/09 QA70-14513-P1 CHKBOX_TO_REPLACE_OR_KEEP
/*
void _update_mask_dependent_ctrls(TreeNode& trGetN)
{
	trGetN.cond.Enable = (trGetN.mask.nVal == mask_mask);
	_update_cond_dependent_ctrls(trGetN);
}
*/
/// end ADD_CONDITION_TO_WCELLMASK_XF

//---- CPY 10/22/09 QA70-14513-P4 NEED_TO_SUPPORT_EUAL_TO_AS_WELL
//uint nFindOption = 0;
//if(cond == cond_greater)
//	nFindOption = MATREPL_TEST_GREATER;
//else if(cond == cond_less)
//	nFindOption = MATREPL_TEST_LESSTHAN;
static uint _cvt_drop_down_to_test_bits(int cond)
{
	uint nn[] = {0, // std
	MATREPL_TEST_GREATER,
	MATREPL_TEST_GREATER | MATREPL_TEST_EQUAL,
	MATREPL_TEST_LESSTHAN,
	MATREPL_TEST_LESSTHAN | MATREPL_TEST_EQUAL,
	MATREPL_TEST_EQUAL};
	
	if(cond < sizeof(nn)/sizeof(uint))
		return nn[cond];
	
	return 0;
}
static void _get_masked_rows(vector<uint>& vn, Column cc, uint nFindOption, double val)
{
	if(0==nFindOption) // nSD
	{
		find_outliers_by_sd(cc, val, vn);
	}
	else // cond == cond_gt etc and existing mask is never considered, we may need to improve later
	{
		vectorbase &vv = cc.GetDataObject();				
		vector vData;
		vData = vv;
		vData.Find(nFindOption, val, vn);
	}
}
//----




void colmask(const Range& irng, const int& cond, const int& nSD, const double& val, const int& abs, const int& keep)
{
	
	///--- CPY 10/22/09 QA70-14513-P1 CHKBOX_TO_REPLACE_OR_KEEP
	/*
	/// EJP 2009-10-21 QA81-14513 ADD_CONDITION_TO_WCELLMASK_XF
	///irng.SetMask(mask);
	if(mask == mask_unmask || cond == cond_none)
		irng.SetMask(mask); // old behavior when not using condition
	else
	{
	*/
	bool bReplace = keep? false:true;
	vector<byte> vMask;
	//---- CPY 10/22/09 QA70-14513-P4 NEED_TO_SUPPORT_EUAL_TO_AS_WELL
	//uint nFindOption = 0;
	//if(cond == cond_greater)
	//	nFindOption = MATREPL_TEST_GREATER;
	//else if(cond == cond_less)
	//	nFindOption = MATREPL_TEST_LESSTHAN;
	uint nFindOption = _cvt_drop_down_to_test_bits(cond);
	if(abs && cond != cond_sd)
		nFindOption |= MATREPL_USE_ABSOLUTE_VALUE_IN_TEST;
	ASSERT(nFindOption==0 || cond != cond_sd);// use 0 for sd test as all those bits are not 0
	//----
	
	int nNumRange = irng.GetNumRanges();
	for(int ii = 0; ii < nNumRange; ii++)
	{
		Worksheet wksSrc;
		int r1, r2, c1, c2;
		irng.GetRange(ii, r1, c1, r2, c2, wksSrc);
		if (!wksSrc)
			continue;
		
		if(c2 < 0)
			c2 = wksSrc.GetNumCols() - 1;//CPY 10/22/09 QA70-14513-P3 NO_WKS_SEL_SHOULD_WORK_ON_WHOLE_SHEET
		
		for (int nCol = c1; nCol <= c2; nCol++)
		{
			Column cc(wksSrc, nCol);
			//----CPY 10/22/09 QA70-14513-P2 SHOULDNOT_CARE_IF_Y
			//if(wksSrc.Columns(nCol).GetType() != OKDATAOBJ_DESIGNATION_Y || is_col_all_text(wksSrc, nCol) > 0)
			//	continue;
			if(cc.GetFormat() == OKCOLTYPE_TEXT)
				continue;
			//----
			vector<uint> vn;
			///--- CPY 10/22/09 QA70-14513-P4 NEED_TO_SUPPORT_EUAL_TO_AS_WELL
			/*
			if(cond == cond_std)
			{
				if(keep) // per Easwar, if not to keep existing mask, then ignore them for SD
					find_outliers_by_sd(cc, nSD, vn);
				else
				{
					//ignore existing masked points
					LTVarTempChange val_mask("@MM", 1);
					find_outliers_by_sd(cc, nSD, vn);
				}
			}
			else // cond == cond_gt etc and existing mask is never considered, we may need to improve later
			{
				vectorbase &vv = cc.GetDataObject();				
				vector vData;
				vData = vv;
				vData.Find(nFindOption, val, vn);
			}
			*/
			double value = 0==nFindOption? nSD:val;
			if(keep) // per Easwar, if not to keep existing mask, then ignore them for SD
				_get_masked_rows(vn, cc, nFindOption, value);
			else
			{
				//ignore existing masked points
				LTVarTempChange val_mask("@MM", 1);
				_get_masked_rows(vn, cc, nFindOption, value);
			}
			//---
			int nColSize = cc.GetUpperBound() + 1; // +1 offset
			vMask.SetSize(nColSize);
			vMask = 0;
			vMask.Replace(vn, 1);
			DatasetObject dsObj(cc);
			dsObj.SetMask(vMask, bReplace);
		}
	}
	//	}///--- CPY 10/22/09 QA70-14513-P1 CHKBOX_TO_REPLACE_OR_KEEP
	/// end ADD_CONDITION_TO_WCELLMASK_XF
	
}

//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 colmask_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return colmask_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	///Jake 06/06/07 ADD_ERROR_CHECKING 
	Range rRange;
	TreeNode tr = trGetN.irng;
	okxf_resolve_tree_construct_range(&tr,&rRange);
	int nNumData= rRange.GetNumData();
	if(0 == nNumData)
	{
		strErrMsg = XFERR_NO_RANGE_SELECTED;
		bOKEnable = false;
	}
	///end ADD_ERROR_CHECKING
	
	/// Kenny 11/04/2009 QA81-14513-P2 XF_COL_MASK_IMPROVE_ERROR_CHECKING
	if ( cond_sd != trGetN.cond.nVal )
	{
		if ( is_empty_or_unassigned(trGetN.val.strVal) )
		{
			strErrMsg = XFERR_REQUIRE_NUMBER;
			bOKEnable = false;
		}
	}
	/// End QA81-14513-P2 XF_COL_MASK_IMPROVE_ERROR_CHECKING
	
	/// EJP 2009-10-21 QA81-14513 ADD_CONDITION_TO_WCELLMASK_XF
	///--- CPY 10/22/09 QA70-14513-P1 CHKBOX_TO_REPLACE_OR_KEEP
	//if(lstrcmpi(lpcszNodeName, "mask") == 0)
	//	_update_mask_dependent_ctrls(trGetN);
	//else
	//----
	if(GETNE_ON_INIT == nEventID || GETNE_ON_THEME == nEventID || lstrcmpi(lpcszNodeName, "cond") == 0)
		_update_cond_dependent_ctrls(trGetN);
	/// end ADD_CONDITION_TO_WCELLMASK_XF
	
	return true;
	

}

int colmask_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 colmask_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	/// EJP 2009-10-21 QA81-14513 ADD_CONDITION_TO_WCELLMASK_XF
	///--- CPY 10/22/09 QA70-14513-P1 CHKBOX_TO_REPLACE_OR_KEEP
	//	_update_mask_dependent_ctrls(trGetN);
	///---
	/// end ADD_CONDITION_TO_WCELLMASK_XF
	
}
//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 colmask_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
