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


#include <GetNBox.h>
#include <image_utils.h>

static void _init_slider(TreeNode& trGetN, int nW, int nH)
{
	String strV;
	if(nW > 0 && nH > 0)
	{
		strV.Format("%d|%d|%d",1,nW,nW-1);
		trGetN.w.SetAttribute(STR_COMBO_ATTRIB,strV);
		strV.Format("%d|%d|%d",1,nH,nH-1);
		trGetN.h.SetAttribute(STR_COMBO_ATTRIB,strV);
		strV.Format("%d|%d|%d",0,nW-1,nW-1);
		trGetN.x.SetAttribute(STR_COMBO_ATTRIB,strV);
		strV.Format("%d|%d|%d",0,nH-1,nH-1);
		trGetN.y.SetAttribute(STR_COMBO_ATTRIB,strV);
	}
	
	trGetN.w.nVal=nW-1;
	trGetN.h.nVal=nH-1;
	trGetN.x.nVal=1;
	trGetN.y.nVal=1;
}

static int _crop_image(BITMAPHANDLE* pLBmp, int& x, int& y , UINT& uWidth, UINT& uHeight)
{
	int nRet=0;

	/// EJP 2008-12-23 v8.0991 QA80-12845 IMPROVE_ROI_CROP
	///// EJP 2007-04-27 v8.0610 QA70-9607 ROI_USE_INTERSECT_RECT
	///*
	//if(x<0||x>pLBmp->Width||y<0||y>pLBmp->Height)
	//{
		//return INTOPTN_OUT_OF_RANGE;
	//}   
	//
	//if(uWidth<0||uWidth>pLBmp->Width||uHeight<0||uHeight>pLBmp->Height)
	//{
		//return INTOPTN_OUT_OF_RANGE;
	//}    
	//*/
	//if( x < 0 )
		//x = 0;
	//else if( x >= pLBmp->Width )
		//x = pLBmp->Width - 1;
	//if( y < 0 )
		//y = 0;
	//else if( y >= pLBmp->Height )
		//y = pLBmp->Height - 1;
//
	//if( uWidth <= 0 )
		//uWidth = pLBmp->Width;
	//if( x + uWidth > pLBmp->Width )
		//uWidth = pLBmp->Width - x;
	//if( uHeight <= 0 )
		//uHeight = pLBmp->Height;
	//if( y + uHeight > pLBmp->Height )
		//uHeight = pLBmp->Height - y;
	///// end ROI_USE_INTERSECT_RECT
	//return L_TrimBitmap(pLBmp, x, y, uWidth, uHeight);
	RECT rectBmp = {0, 0, 0, 0};
	rectBmp.right = pLBmp->Width;
	rectBmp.bottom = pLBmp->Height;

	RECT rectCropRequest;
	rectCropRequest.left = x;
	rectCropRequest.top = y;
	rectCropRequest.right = x + uWidth;
	rectCropRequest.bottom = y + uHeight;

	RECT rectCrop;
	if( IntersectRect(&rectCrop, &rectBmp, &rectCropRequest) )
	{
		/// YuI 06/08/09 QA70-13748_P1 IMAGE_CROP_CORRUPTS_DATA_MODE
		// I do not see why we add 1 to width and height.
		// it does not produce correct result.
		//	return L_TrimBitmap(pLBmp, rectCrop.left, rectCrop.top, rectCrop.right - rectCrop.left + 1, rectCrop.bottom - rectCrop.top + 1);
		return L_TrimBitmap(pLBmp, rectCrop.left, rectCrop.top, rectCrop.right - rectCrop.left, rectCrop.bottom - rectCrop.top);
		/// end IMAGE_CROP_CORRUPTS_DATA_MODE
	}
	return XFERR_NO_RECT_INTERSECT;
	/// end IMPROVE_ROI_CROP	
}


void mCrop(const int& x, const int& y, const int& w, const int& h, const MatrixObject& im, MatrixObject& om)
{
	
	int nNumCols = im.GetNumCols();
	int nNumRows = im.GetNumRows();
	
	double dXMin, dXMax, dYMin, dYMax;
	im.GetXY(dXMin, dYMin, dXMax, dYMax);
	
	double dXDelta, dYDelta;
	dXDelta = (dXMax - dXMin) / (double)(nNumCols - 1);
	dYDelta = (dYMax - dYMin) / (double)(nNumRows - 1);
	
	int nX = x, nY = y;
	if( nX < 0 )
		nX = 0;
	else if( nX >= nNumCols )
		nX = nNumCols - 1;
	if( nY < 0 )
		nY = 0;
	else if( nY >= nNumRows )
		nY = nNumRows - 1;
	
	UINT nWidth = w, nHeight = h;
	if( nWidth == 0 )
		nWidth = nNumCols;
	if( nX + nWidth > nNumCols )
		nWidth = nNumCols - nX;
	if( nHeight <= 0 )
		nHeight = nNumRows;
	if( nY + nHeight > nNumRows )
		nHeight = nNumRows - nY;
	
	if( im.HasData() )
	{
		/// TD 01-22-2009 QA80-12333_S2 EXPOSE_AND_USE_CopyMatrixObj_FROM_OC 
		//out_str("mCrop currently only supports Image Matrix.");
		//return;
		RECT rectCrop;
		rectCrop.left = nX;
		rectCrop.top = nY;
		rectCrop.right = nX + nWidth;
		rectCrop.bottom = nY + nHeight;
		im.CopyToMatrix(om, &rectCrop, TRUE);
		/// end EXPOSE_AND_USE_CopyMatrixObj_FROM_OC
	}
	else
	{
		Image img(im), oimg(om);
		oimg.SetLBmp(img.GetLBmp(), TRUE);
		pBITMAPHANDLE phBmp = oimg.GetLBmp();
		int nRet = _crop_image(phBmp, nX, nY, nWidth, nHeight);
		
		if(nRet < MAX_ERROR_CODE_FROM_LT)
			XF_THROW_EX(XFERR_LEADTOOLS_FUNCTION_UNKNOWN_ERR, nRet);
		
		if(nRet !=  SUCCESS)
			XF_THROW(nRet);
	
		
		if( om != im )
			om.SetLeadBitmap(phBmp);
		/// YuI 06/08/09 QA70-13748_P1 IMAGE_CROP_CORRUPTS_DATA_MODE
		else
			om.SetLeadBitmap(NULL, true, false, SLB_NO_RESET_XYMAP | SLB_SET_DATA_DIMENSIONS);
		/// end IMAGE_CROP_CORRUPTS_DATA_MODE
	}	
	
	dXMin += nX * dXDelta;
	dXMax = dXMin + (nWidth - 1) * dXDelta;
	dYMin += nY * dYDelta;
	dYMax = dYMin + (nHeight - 1) * dYDelta;
	om.SetXY(dXMin, dYMin, dXMax, dYMax);
		
}

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

}

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