#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>


//put additional include files here

/*------------------------------------------------------------------------------*
* Modification Log:																*
*	Sim 09-15-2009 QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE				*
*-------------------------------------------------------------------------------*/

//put your own support static functions here
///---Sim 09-15-2009 QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
static bool _is_in_same_sheet(const Range& rng)
{
	if ( !(rng && rng.IsValid() && rng.GetNumRanges() > 0) )
		return false;
	
	Worksheet wksRef;
	string strBookSheet;
	for ( int ii = 0; ii < rng.GetNumRanges(); ii++ )
	{
		int iR1, iC1, iR2, iC2;
		Worksheet wks;
		if ( rng.GetRange(ii, iR1, iC1, iR2, iC2, wks) && wks )
		{
			if ( !wksRef )
			{
				wksRef = wks;
				continue;
			}
			
			if ( !is_same_layer(wksRef, wks) )
				return false;
		}
	}
	
	return true;
}

static bool _get_bounding_range(const Range& rng, int& nR1, int& nC1, int& nR2, int& nC2)
{
	if ( !(rng && rng.IsValid() && rng.GetNumRanges() > 0) )
		return false;
	
	if ( !_is_in_same_sheet(rng) )
		return false;
	
	vector<int> vnCols, vnRows;
	
	Worksheet wks;
	for ( int ii = 0; ii < rng.GetNumRanges(); ii++ )
	{
		int iR1, iC1, iR2, iC2;
		if ( rng.GetRange(ii, iR1, iC1, iR2, iC2, wks) && wks )
		{
			if ( iC2 < 0 )
				iC2 = wks.GetNumCols() - 1;
			if ( iR2 < 0 )
				iR2 = wks.GetNumRows() - 1;

			vnCols.Add(iC1);
			vnCols.Add(iC2);
			vnRows.Add(iR1);
			vnRows.Add(iR2);
		}
	}
	
	if ( !wks )
		return false;
	
	double dMin, dMax;
	
	vnCols.GetMinMax(dMin, dMax);
	nC1 = dMin;
	nC2 = dMax;
	
	vnRows.GetMinMax(dMin, dMax);
	nR1 = dMin;
	nR2 = dMax;
	
	if ( nC1 > nC2 || nR1 > nR2 )
		return false;
	
	return true;
}
///---END QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE


void copydata(const Range& irng, Range& orng, const int& clear)
{
	///---Sim 09-15-2009 QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
	int iR1Bound, iC1Bound, iR2Bound, iC2Bound;	
	if ( !_get_bounding_range(irng, iR1Bound, iC1Bound, iR2Bound, iC2Bound) )
		XF_THROW(CER_EXTRACTBYROWSERR_MULTIPLE_SHEETS);
	///---END QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
	
	int iR1Src, iC1Src, iR2Src, iC2Src;
	int iR1Dst, iC1Dst, iR2Dst, iC2Dst;
	Datasheet dsSrc, dsDst;
	
	irng.GetRange(0, iR1Src, iC1Src, iR2Src, iC2Src, dsSrc);
	orng.GetRange(0, iR1Dst, iC1Dst, iR2Dst, iC2Dst, dsDst);
	
	Worksheet wksSrc(dsSrc.m_strBookSheet);
	if (!wksSrc)
	{
		XF_THROW(CER_INVALID_RANGE);
	}
	
	Worksheet wksDst(dsDst.m_strBookSheet);
	if (!wksSrc)
	{
		XF_THROW(CER_INVALID_OUT_RANGE);		
	}
	
	///---Sim 09-15-2009 QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
	//matrix mTemp(iR2Src-iR1Src+1,iC2Src-iC1Src+1);
	//
	//if (!mTemp.CopyFrom(wksSrc, iR1Src,iC1Src, iR2Src, iC2Src))
	//{
		//XF_THROW(CER_COPY_RANGE);	
	//}
	//
	//mTemp.CopyTo(wksDst, 0, 0, -1, -1, iR1Dst, iC1Dst, false);
	
	if ( clear )
	{
		matrix mTemp(iR2Bound-iR1Bound+1, iC2Bound-iC1Bound+1);
		mTemp = NANUM;
		
		mTemp.CopyTo(wksDst, 0, 0, -1, -1, iR1Dst, iC1Dst, false);
	}
	
	for ( int ii = 0; ii < irng.GetNumRanges(); ii++ )
	{
		//Worksheet wksSrc;
		if ( !(irng.GetRange(ii, iR1Src, iC1Src, iR2Src, iC2Src, wksSrc) && wksSrc) )
			continue;
		if ( iC2Src < 0 )
			iC2Src = wksSrc.GetNumCols() - 1;
		if ( iR2Src < 0 )
			iR2Src = wksSrc.GetNumRows() - 1;
		
		matrix mTemp(iR2Src-iR1Src+1, iC2Src-iC1Src+1);
		if (!mTemp.CopyFrom(wksSrc, iR1Src, iC1Src, iR2Src, iC2Src))
		{
			XF_THROW(CER_COPY_RANGE);	
		}
		
		int nR1To = iR1Dst + (iR1Src - iR1Bound);
		int nC1To = iC1Dst + (iC1Src - iC1Bound);
		
		mTemp.CopyTo(wksDst, 0, 0, -1, -1, nR1To, nC1To, false);
	}
	///---END QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
	
	//vector vv;
	//if (!mTemp.GetAsVector(vv,false))
	//{
		//XF_THROW(ERR_FAIL_COPY_AS_VECTOR);
	//}
	//
	//int iNumRows = wksDst.GetNumRows();
	//int iNumCols = wksDst.GetNumCols();
	//
	//if (iR2Src==-1) 
	//{
		//iR2Src = iR1Src - 1 + vv.GetSize()/(iC2Src-iC1Src+1);
	//}
	//
	//iC2Dst = iC1Dst + iC2Src - iC1Src;
	//iR2Dst = iR1Dst + iR2Src - iR1Src;
	//
	//while (iC2Dst>=iNumCols)
	//{
		//wksDst.AddCol();
		//iNumCols++;
	//}
	//
	//if (iR2Dst>=iNumRows) wksDst.AppendRows(iR2Dst-iNumRows+1);
	//
	//
	//int ii, jj;
	//int iIndexVector=0;
	//for (ii=iC1Dst; ii<=iC2Dst; ii++)
	//{
		//for (jj=iR1Dst; jj<=iR2Dst; jj++)
		//{
			//wksDst.SetCell(jj,ii, vv[iIndexVector++]);
		//}
	//}
}

//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 copydata_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return copydata_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	///---Sim 09-15-2009 QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
	if ( GETNE_ON_INIT == nEventID || 0 == lstrcmp(lpcszNodeName, "irng") )
	{
		TreeNode trRange = trGetN.irng;
		Range rng;
		if ( okxf_resolve_tree_construct_range(&trRange, &rng) )
		{
			if ( !_is_in_same_sheet(rng) )
			{
				strErrMsg = CER_EXTRACTBYROWSERR_MULTIPLE_SHEETS;
				bOKEnable = false;
			}
		}
	}
	///---END QA81-14323 COPY_COL_DATA_SUPPORT_MULTI_SUB_RANGE
	
	return false;

}

int copydata_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 copydata_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{

}
//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 copydata_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
