#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here
#include <event_utils.h>
#include <report_utils.h>
#include <ReportTree.h>
#include <o8dlg.h>
//put your own support static functions here
BOOL	plot_paretobin_CreatePlots(GraphLayer& gl, DataRange& dr, TreeNode& trGetN, BOOL bFromAutoUpdate)
{	
	return plot_pareto_chart(gl, dr, trGetN, bFromAutoUpdate);
}

static bool _output_plot_data(const DataRange& datarng, const DataRange& countrng, ReportData& rd)
{
	// get data from range
	Worksheet wks;
	int r1, c1, r2, c2;
	datarng.GetRange(0, r1, c1, r2, c2, wks);
	
	Column colData(wks, c1);
	ASSERT(colData.IsValid());
	if( !colData.IsValid() )
		return false;
	
	vector<string> vsData;
	colData.GetStringArray(vsData, r1, r2);
	
	// get count data from range
	countrng.GetRange(0, r1, c1, r2, c2, wks);
	Column colCount(wks, c1);
	ASSERT(colCount.IsValid());
	if( !colCount.IsValid() )
		return false;

	vector vCount;
	vCount = colCount.GetDataObject();
	if( r1 != 0 || r2 != -1)
		vCount.GetSubVector(vCount, r1, r2);
	
	// check the size of two ranges
	if( vsData.GetSize() != vCount.GetSize() )
	{
		int size = vsData.GetSize() < vCount.GetSize()? vsData.GetSize() : vCount.GetSize();
		vsData.SetSize(size);
		vCount.SetSize(size);
	}
	
	// sort
	vector<uint> vnIndeces;
	vCount.Sort(SORT_DESCENDING, FALSE, vnIndeces);
	vsData.Reorder(vnIndeces);
	
	vCount.TrimRight();
	if( vCount.GetSize() != vsData.GetSize() )
		vsData.SetSize(vCount.GetSize());
	
	// calculate cumulative requency
	double dSum;
	vCount.Sum(dSum);
	
	vector vFreq(vCount.GetSize());
	for(int nn = 0; nn < vFreq.GetSize(); nn++)
	{
		vFreq[nn] = vCount[nn] / dSum * 100;
		if( nn > 0 )
			vFreq[nn] += vFreq[nn-1];
	}
	
	// get long name of data column	
	string strTableLabel = colData.GetLongName();
	if( strTableLabel.IsEmpty() )
		strTableLabel = colData.GetName();
	
	// output report data
	ReportTable rt = rd.CreateTable("FreqCount",  strTableLabel, FREQ_REPORT_TABLE);
	TreeNode trData = rt.AddColumn(vsData, "Data1", _DISC_FREQS_DATA, _L("Data"), OKDATAOBJ_DESIGNATION_X);
	trData.SetAttribute(STR_COL_FORMAT_ATTRIB, OKCOLTYPE_TEXT);
	rt.AddColumn(vCount, "Count1", _DISC_FREQS_FREQS, _L("Count"), OKDATAOBJ_DESIGNATION_Y);
	rt.AddColumn(vFreq, "CumFreq1", _DISC_FREQS_PERC, _L("Cumulative Frequency"), OKDATAOBJ_DESIGNATION_Y);
	return true;
}

#define		STR_SELECT_COULMN_FOR_DATA				_L("Please select one column for Data Input Range")
#define		STR_SELECT_COULMN_FOR_COUNT				_L("Please select one column for Count Input Range")

static bool _check_input_range(TreeNode& trRange, LPCSTR lpcszInputErr, string& strErrMsg, bool& bOKEnable)
{
	int	nErrCode = check_1_data(trRange, false, true);		
	if (nErrCode != CER_NO_ERROR)
	{
		if( CER_COL_NUM_NOT_ONE == nErrCode )
		{
			strErrMsg = lpcszInputErr;
		}
		else
			strErrMsg = nErrCode;
		bOKEnable = false;
		return false;
	}	
	return true;
}


void plot_paretobin(const Range& datarng, const Range& countrng, ReportData& rd)
{
	
	_output_plot_data(datarng, countrng, rd);
	
}

//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 plot_paretobin_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return plot_paretobin_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	TreeNode trData = trGetN.datarng;
	if( _check_input_range(trData, STR_SELECT_COULMN_FOR_DATA, strErrMsg, bOKEnable) )
	{
		TreeNode trCount = trGetN.countrng;
		_check_input_range(trCount, STR_SELECT_COULMN_FOR_COUNT, strErrMsg, bOKEnable);
	}	
	
	return false;

}

int plot_paretobin_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 plot_paretobin_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		if(is_use_origin_chm())
			trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_plot_paretobin);
	}	
}
//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 plot_paretobin_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
