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

//Modification log
// CPY 5/4/07 change varaible named res to crop, change imgb to allow theme to remember, added option to output to results log
// CPY 5/4/07 PROPER_CROPPING_IN_RESULT
// CPY 5/6/07 ALLOW_IMGB_FROM_THEME

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

//------ CPY 5/6/07 ALLOW_IMGB_FROM_THEME
static BOOL _check_input_arg(TreeNode& trGetN, string& strErrMsg, pBITMAPHANDLE* ppimgb, pBITMAPHANDLE* ppimgi)
{
	string strimg1=trGetN.imgb.strVal;
	string strimg2=trGetN.img.strVal;

	Image imgb;
	okxf_resolve_string_get_origin_object(strimg1, &imgb);
	Image imgi;
	okxf_resolve_string_get_origin_object(strimg2, &imgi);

	///Sandy 2007-5-8 need to clear up the object when it is invalid
	//if(!imgb.IsValid()|| !imgi.IsValid())
	//{
		//strErrMsg = XFERR_INVALID_IMAGE_TO_BLEND;
		//return false;
	//}
	if(!imgi.IsValid())
	{
		trGetN.img.Reset(true);
		strErrMsg = XFERR_INVALID_IMAGE_TO_BLEND;
		return false;
	}
	
	if(!imgb.IsValid())
	{
		trGetN.imgb.Reset(true);
		strErrMsg = XFERR_INVALID_IMAGE_TO_BLEND;
		return false;
	}
	///-----
	
	*ppimgb = imgb.GetLBmp();
	*ppimgi = imgi.GetLBmp();
	return true;
}
//-------

static void _update_sliders(TreeNode& trGetN, int nw1, int nh1, int nw2, int nh2)
{
	String strV;
	if(nw1 > 0 && nh1 > 0 && nw2 > 0 && nh2 > 0 )
	{
		strV.Format("%d|%d|%d",-nw1+1,nw2-1,nw1+nw2-2);
		trGetN.x.SetAttribute(STR_COMBO_ATTRIB,strV);
		strV.Format("%d|%d|%d",-nh1+1,nh2-1,nh1+nh2-2);
		trGetN.y.SetAttribute(STR_COMBO_ATTRIB,strV);
	}
	
}

enum{
	IMGB_ORIGINAL = 0,
	IMGB_INTERSECT,

};
static int _alpha_blend_image(BITMAPHANDLE* pDstLBmp,BITMAPHANDLE* pSrcLBmp, int nOpacity, int x, int y, int nOption)
{
	int  nXSize, nYSize;
	nXSize=(pSrcLBmp->Width );
	nYSize=(pSrcLBmp->Height);
	int nRet =  L_AlphaBlendBitmap(pDstLBmp,x, y, nXSize, nYSize, pSrcLBmp, 0, 0, nOpacity);
	if(SUCCESS != nRet)
		return nRet;
	
	if(nOption == IMGB_INTERSECT)
	{
		//-------CPY 5/4/07 PROPER_CROPPING_IN_RESULT
		//return L_TrimBitmap(pDstLBmp, x, y, nXSize-x, nYSize-y);
		RECT rSrc = {0}, rDest = {0};
		rSrc.right = pSrcLBmp->Width, rSrc.bottom = pSrcLBmp->Height;
		rDest.right =pDstLBmp->Width,rDest.bottom = pDstLBmp->Height;
		OffsetRect(&rSrc, x, y);
		RECT rResult;
		if(!IntersectRect(&rResult, &rSrc, &rDest))
			return -1;
		int nCropWidth = RECT_WIDTH(rResult);
		int nCropHeight = RECT_HEIGHT(rResult);

		return L_TrimBitmap(pDstLBmp, rResult.left, rResult.top, nCropWidth, nCropHeight);
		//------- end PROPER_CROPPING_IN_RESULT
	}
	
	return SUCCESS;
}

//static int _preview_alpha_blend_image(BITMAPHANDLE* pDstLBmp, BITMAPHANDLE* pSrcLBmp , int nOpacity, int x, int y)
//{
	//int nXSize, nYSize;
	//
	////nXSize=(pDstLBmp->Width + pSrcLBmp->Width );
	////nYSize=(pDstLBmp->Height + pSrcLBmp->Height);
	//
	//nXSize=(pSrcLBmp->Width );
	//nYSize=(pSrcLBmp->Height);
	//
	//int nRet =  L_AlphaBlendBitmap(pDstLBmp,x, y, nXSize, nYSize, pSrcLBmp, 0, 0, nOpacity);	
	//if(SUCCESS != nRet)
		//return nRet;
	//
	////return L_AutoTrimBitmap(pDstLBmp, 5);
	//return true;
//
//}
//

void imgBlend(const Image& img, const Image& imgb, const int& opacity, Image& oimg, const int& x, const int& y, const int& crop)
{
	
	
	oimg.SetLBmp(img.GetLBmp(), true);
	{
	
		BITMAPHANDLE* pdstBmp = oimg.GetLBmp();
		BITMAPHANDLE* pbldBmp = imgb.GetLBmp();
		
		if(!pdstBmp || !pbldBmp)
			XF_THROW(XFERR_INVALID_IMAGE_TO_BLEND);
		
	    int nRet =_alpha_blend_image(pdstBmp,pbldBmp, opacity, x, y, crop);
		
		
		if(nRet < MAX_ERROR_CODE_FROM_LT)
		{
			XF_THROW_EX(XFERR_LEADTOOLS_FUNCTION_UNKNOWN_ERR, nRet);
		}
		
		if(nRet !=  SUCCESS)
		{
			XF_THROW(nRet);	
		}
	}
	
	
}

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

}

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


// this is called when the GetNImageBox dialog is open
// bUpdateGrid = false when entering this function
// you need to set bUpdateGrid = true if you need to modify trGetN data and want to see the
// grid updated, for example
// trGetN.angle.nVal = 0; // force rotation to init to 0
// bUpdateGrid = true;
// bOKEnable is default = true, you may add code to check trGetN and decide that the OK button should be disabled, then set this to false
// example: 
// if(0==trGetN.angle.nVal) // no change, no point to click Ok to do nothing
//    bOKEnable = false; 
static void GetNImageBox_OnInit(TreeNode& trGetN, ImageControlBase* pimgCntrl, bool& bUpdateGrid, bool& bOKEnable, string& strErrMsg)
{

	pBITMAPHANDLE pPreviewBitmap;
	pPreviewBitmap=pimgCntrl->GetBitmapHandlePtr();
	//------- CPY 5/6/07 ALLOW_IMGB_FROM_THEME
	/*strErrMsg = XFERR_INVALID_IMAGE_TO_BLEND;
	bOKEnable = false;*/
	pBITMAPHANDLE pimgb=NULL, pimgi=NULL;
	bOKEnable = _check_input_arg(trGetN, strErrMsg, &pimgb, &pimgi);
	if(!bOKEnable)
		return ;
	
	if(pimgb && pimgi)
		_update_sliders(trGetN, pimgb->Width, pimgb->Height, pimgi->Width, pimgi->Height);
	//-------
	
	int nRet =  _alpha_blend_image(pPreviewBitmap, pimgb, trGetN.opacity.nVal,trGetN.x.nVal,trGetN.y.nVal, IMGB_ORIGINAL);
	if( SUCCESS != nRet)
	{
		strErrMsg = nRet;
		bOKEnable = false;
	}		
	
	bUpdateGrid = true;
	
}

// this is called whenever any controls in the grid is modified by the user
// upon entering function
// bUpdatePreview = true;// to update the preview image pPreviewBitmap
// bUpdateGrid = false; // event triggered by grid change, so default no need to update again
// if you want to modify other controls in the grid, then you need to set bUpdateGrid to true
// bOKEnable is default = true, you may add code to check trGetN and decide that the OK button should be disabled, then set this to false
static void GetNImageBox_OnChange(BITMAPHANDLE* pPreviewBitmap, TreeNode& trGetN, TreeNode& trNode, ImageControlBase* pimgCntrl, bool& bUpdatePreview, bool& bUpdateGrid, bool& bOKEnable, string& strErrMsg)
{

	//------ CPY 5/6/07 ALLOW_IMGB_FROM_THEME
	/*
	string strimg1=trGetN.imgb.strVal;
	string strimg2=trGetN.imgi.strVal;
	
	Image imgb;
	okxf_resolve_string_get_origin_object(strimg1, &imgb);
	Image imgi;
	okxf_resolve_string_get_origin_object(strimg2, &imgi);

	if(!imgb.IsValid()|| !imgi.IsValid())
	{
		strErrMsg = XFERR_INVALID_IMAGE_TO_BLEND;
		bOKEnable = false;
		return;
	}
	BITMAPHANDLE* pimgb = imgb.GetLBmp();
	BITMAPHANDLE* pimgi = imgi.GetLBmp();
	*/
	pBITMAPHANDLE pimgb, pimgi;
	bOKEnable = _check_input_arg(trGetN, strErrMsg, &pimgb, &pimgi);
	if(!bOKEnable)
		return;
	//-------
	
	if(trNode.IsValid())
	{
		if(trNode.tagName == "imgb")
		{
			_update_sliders(trGetN, pimgb->Width, pimgb->Height, pimgi->Width, pimgi->Height);
		}
	}	

	int nRet =  _alpha_blend_image(pPreviewBitmap, pimgb, trGetN.opacity.nVal,trGetN.x.nVal,trGetN.y.nVal, IMGB_ORIGINAL);
	if( SUCCESS != nRet)
	{
		strErrMsg = nRet;
		bOKEnable = false;
		bUpdatePreview=false;
	}		
	else
		bUpdatePreview=true;
	
	
	//int n1 = pPreviewBitmap->Width;
	//int n2 = pPreviewBitmap->Height;
	//
	//int n3 = pimgi->Width;
	//int n4 = pimgi->Height;



}
	
int GetNImageBox_imgBlend(TreeNode& trGetN, int nRow, int nCol, TreeNode& trNode, DWORD dwCntrl, int nType, WndContainer& theDlg, ImageControlBase* pimgCntrl)
{
	return xf_GetNImageBox_event_handler(trGetN, nRow, nCol, trNode, dwCntrl, nType, pimgCntrl,
								GetNImageBox_OnInit, GetNImageBox_OnChange);	
}
