#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
#include <event_utils.h>
//put additional include files here

//put your own support static functions here
enum
{
	_RANK_NUM_INTERVAL,
	_RANK_USER_DEFINE,
};

static void _reset(TreeNode tr, bool bEnable)
{
	tr.Enable = bEnable ;
	//if (!bEnable)
		//tr.strVal = " ";
}

static void _set_threshods(string& strThreshold, const double dMin, const double dMax, const double dInterval)
{
	if (dMin != NANUM && dMax != NANUM && dInterval != NANUM)
	{
	
		double dInc = (dMax - dMin)/dInterval;
		for (int ii = 0; ii < (int)dInterval-1; ii++)
		{
			double dThredholds = dMin + ii * dInc;
			strThreshold += ftoa(dThredholds) + ' ';
		}
		strThreshold += dMin + (dInterval-1) * dInc;
	}else
	strThreshold = ' ';
	
}

static bool _getn_set_thresholds(TreeNode& trGetN)
{
	if (!trGetN)
		return false;
	
	bool bAutoThresdhold = 1 - trGetN.method.nVal;
	
	trGetN.threshold.Enable = !bAutoThresdhold;
	trGetN.interval.Enable = bAutoThresdhold;
	trGetN.max.Enable = bAutoThresdhold;
	trGetN.min.Enable = bAutoThresdhold;
	
	if (bAutoThresdhold) 
	{
		string strThresholds;
		_set_threshods(strThresholds, trGetN.min.dVal, trGetN.max.dVal, trGetN.interval.dVal);
		trGetN.threshold.strVal = strThresholds;
	}else
	{
		string strThresholds = trGetN.threshold.strVal;
		vector vThresholds;
		int nThresholds = strThresholds.GetTokens(vThresholds);
		trGetN.interval.dVal = nThresholds;
	}
	
	double dIntervals = trGetN.interval.dVal;
	if (dIntervals != NANUM)
	{
		set_value_for_auto_and_unassigned(trGetN.from, 1);
		set_value_for_auto_and_unassigned(trGetN.to, trGetN.interval.dVal);
		set_value_for_auto_and_unassigned(trGetN.increment, (trGetN.max.dVal - trGetN.min.dVal) / dIntervals);
	}	
	
	return true;
}




void rank(const Range& irng, const double& interval, const double& from, const double& to, const int& method, const string& threshold, const double& min, const double& max, Range& orng)
{
	
	if (1 != irng.GetNumData(DRR_NO_WEIGHTS))
	{
		XF_THROW(CER_COL_NUM_NOT_ONE);
	}
	if (!check_min_max(min, max) )
	{
		XF_THROW(CER_MIN_MAX);
	}
	if ( !method && !check_intervals(interval) )
	{
		XF_THROW(CER_INVALID_INTERVAL_NUM);
	}
	vector vData;
	irng.GetData(vData, 0);	
	vData.Trim();
	int nSize = vData.GetSize();
	if (0 == nSize )
	{
		XF_THROW(CER_NO_DATA);
	}
	vector vThresholds, vRanks;
	vRanks.SetSize(nSize);
	
	int nRanks;
	int nThresholds = threshold.GetTokens(vThresholds);//put the user-defined thresholds in vector
	nRanks = vThresholds.GetSize();
	
	vThresholds.Sort();
	vThresholds.InsertAt(nRanks, max);
	
	double dRanksInc = (to - from)/(nRanks-1);
	vRanks = NANUM;
	for (int ii = 0; ii < vData.GetSize(); ii++)
	{
		for (int jj = 0; jj < nRanks; jj++)
		{
			if (vData[ii] >= vThresholds[jj]&& vData[ii] < vThresholds[jj+1])
			{
				vRanks[ii] = from + jj * dRanksInc;
				break;
			}
		}
		
	}
	orng.SetColumnData(vRanks, true, 0)
	
}

//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 rank_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return rank_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	Range rData;
	TreeNode tr = trGetN.irng;
	okxf_resolve_tree_construct_range(&tr, &rData);
	if (rData)
	{
		vector vData;
		rData.GetData(vData, 0);
		set_round_limits(vData, trGetN.min, trGetN.max);
	}
	
	_getn_set_thresholds(trGetN);
	
	bool bAutoThresdhold = 1 - trGetN.method.nVal;
	int nErrCode = CER_NO_ERROR;
	nErrCode = check_1_data(trGetN.irng);
	if (CER_NO_ERROR == nErrCode && !check_min_max(trGetN.min.dVal, trGetN.max.dVal) )
	{
		nErrCode = CER_MIN_MAX;
	}
	if (CER_NO_ERROR == nErrCode && bAutoThresdhold && !check_intervals(trGetN.interval))
	{
		nErrCode = CER_INVALID_INTERVAL_NUM;
	}
	if (CER_NO_ERROR == nErrCode && !bAutoThresdhold && !check_delimiter_space(trGetN.threshold.strVal))
	{
		nErrCode = CER_INVALID_THRESHOLD;
	}
	if(CER_NO_ERROR != nErrCode)
	{
		strErrMsg = nErrCode;
		bOKEnable = false;
	}
	
	return true;
	

}

int rank_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 rank_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	
	if(0 == nGetNDialog || -1 == nGetNDialog)
	{
		Range rData;
		TreeNode tr = trGetN.irng;
		okxf_resolve_tree_construct_range(&tr, &rData);
		if (rData)
		{
			vector vData;
			rData.GetData(vData, 0);
			set_round_limits(vData, trGetN.min, trGetN.max);
		}
		_getn_set_thresholds(trGetN);
	}
	
}
//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 rank_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
