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

//put your own support static functions here
static int _check_input(TreeNode& trGetN)
{
	TreeNode trRange = trGetN.irng;
	DataRange rData;
	okxf_resolve_tree_construct_range(&trRange, &rData);
	
	int r1, r2, c1, c2;
	Datasheet ds;
	if(!rData || !rData.GetNumRanges() || !rData.GetRange( 0, r1, c1, r2, c2, ds) || c1!=c2)
	{
		return CER_NOT_SINGLE_RANGE;		// Please select a range with only one subrange.
	}
	
	if( trGetN.num.nVal < 2 )
		return XFERR_MIN_KEEP_DUPLICATE;

	return CER_NO_ERROR;
}


void wkeepdup(const Range& irng, const int& num, const int& sensitive, const int& undo, Worksheet& ow)
{
	if( num < 2 )
		XF_THROW(XFERR_MIN_KEEP_DUPLICATE);
	
	// worksheet
	Worksheet wksSrc;
	int r1, c1, r2, c2;
	irng.GetRange(0, r1, c1, r2, c2, wksSrc);
	if(!wksSrc)
		XF_THROW(XFERR_INVALID_RANGE);
	
	vector<string> vsCol;
	Column col(wksSrc, c1);
	if( !col )
		XF_THROW(XFERR_INVALID_RANGE);
	col.GetStringArray(vsCol, r1, r2);
	
	if(!ow)
		XF_THROW(XFERR_INVALID_RANGE);
	
	if(wksSrc != ow)
	{
		wksSrc.CopyTo(ow, 0, -1, 0, -1, 0, -1, CPYT_COPY_COLUMN_FORMAT|CPYT_COPY_COLUMN_LABELS|CPYT_COPY_COLUMN_DESIGNATIONS);
	}
	
	// get rows indices to delete
	vector<int> vnMapIndices;
	vector<uint> vnR1s;
	vector<uint> vnOccurrences;
	int nDup = vsCol.FindDuplicates(vnMapIndices, vnR1s, sensitive, vnOccurrences);
	
	vnMapIndices.Replace(0, vnOccurrences.GetSize(), MATREPL_TEST_LESSTHAN);		// -1 for the corresponding value appears only once
	vnOccurrences.Add(1);															// replace it with the index of 1 in vnOccurrences
	
	vector<uint> vnIndices;
	vnIndices = vnMapIndices;
	vnOccurrences.GetSubVector(vnMapIndices, vnIndices);			// vnMapIndices stores the counts
	
	int nRows = vnMapIndices.Find(MATREPL_TEST_LESSTHAN, num, vnIndices);
	if(vnIndices.GetSize() > 0)
		vnIndices = vnIndices + r1;		// offset
	
	// delect rows
	///Kyle 09/19/2010 ORG-1007-P1 WDELDUP_IMPROVE_SPEED
	/*
	vector<int> vnRowBegin;
	vnRowBegin = vnIndices;
	if(ow.SetSelectedRange( vnRowBegin ))
	{
		ow.DeleteSelection(undo);
		string strMsg;
		strMsg.Format(_L("%d row(s) were deleted"), vnRowBegin.GetSize());
		warning_msg_box(strMsg, false, 'I');
	}
	else
		printf("failed to select rows in %s, it might be hidden\n", ow.GetName());
	
	ow.SetSelectedRange( NULL );//unsel all, will trigger internal clean up for temp win created for hidden book as well
	*/
	if( worksheet_delete_rows(ow, vnIndices, undo) )
	{
		string strMsg;
		strMsg.Format(_L("%d row(s) were deleted"), vnIndices.GetSize());
		warning_msg_box(strMsg, false, 'I');
	}
	else
		printf("failed to select rows in %s, it might be hidden\n", ow.GetName());
	///End WDELDUP_IMPROVE_SPEED
}

//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 wkeepdup_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return wkeepdup_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	int nErrCode = _check_input(trGetN);
	if( nErrCode != CER_NO_ERROR)
	{
		strErrMsg = nErrCode;
		bOKEnable = false;
	}
	return false;

}

int wkeepdup_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 wkeepdup_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if( nGetNDialog == 0 && !(dwCntrl & LTXF_SHOW_DIALOG) )
	{
		if( CER_NO_ERROR != _check_input(trGetN) )
			nRet = XFEVT_ABORT;
	}
}
//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 wkeepdup_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
