#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	option_full,
	option_rec,
};
//put additional include files here

#include <GetNBox.h> 
#include <image_utils.h>
#include <..\Originlab\matdata_utils.h>
#include <..\originlab\grobj_utils.h>
#include <..\originlab\ocImgRoiPreview.h>

///temp add by Sandy
#include <xfgraph_utils.h>
//put your own support static functions here
enum{
	IMG_RESCALE_FULL,
	IMG_RESCALE_ROI,
};

#define IMG_RESCALE_ROI_NAME "imgRescaleROI"
#define _USER_EVENT_ID     1

void events_from_imgRescale_ROI(int nID)
{
	post_getn_dialog_message(WM_USER_ON_GRAPH_OBJECT_CHANGE, 0);
}


static bool _init_rect(TreeNode& trAnchor, MatrixLayer& ml)
{
	GraphObject go;
	
	if(!trAnchor.IsValid())
		return false;

	remove_GraphObjects_with_prefix(ml, IMG_RESCALE_ROI_NAME);
	if(!read_and_create_anchors_from_tree(ml, trAnchor, IMG_RESCALE_ROI_NAME, go))
	{
		MatrixObject m = ml.MatrixObjects(0);

		double  dX0, dY0, dX1, dY1;
		m.GetXY(dX0, dY0, dX1, dY1);
		double dCX = (dX1-dX0)/2;
		double dCY = (dY1-dY0)/2;
		double dRX = abs(dX1-dX0)/4;
		double dRY = abs(dY1-dY0)/4;
		
		if( !add_rect(ml, go, dCX-dRX, dCY-dRY, dCX+dRX, dCY+dRY, INDEX_COLOR_TRANSPARENT,  ATTACH_TO_SCALE, LN_FREE, false,  false) )
			return false;
			
		go.SetName(IMG_RESCALE_ROI_NAME);
		save_anchors_to_tree(ml,trAnchor, IMG_RESCALE_ROI_NAME)
		
	}
	
	set_go_border_color(go, SYSCOLOR_GREEN);
	set_LT_script(go, "events_from_imgRescale_ROI(0);" , GRCT_SIZEMOVE);	
	go.Show();
	
	return true;
}

static bool _show_rect(MatrixLayer& ml, bool bShow = true)
{
	GraphObject go = ml.GraphObjects(IMG_RESCALE_ROI_NAME);
	if(!go)
	{
		return false;
	}
	go.Show(bShow);
	
	MatrixPage mp = ml.GetPage();
	mp.Refresh();
	
	return true;
}


void imgScale(MatrixObject& m, const int& option, const double& x0, const double& y0, const double& x1, const double& y1, const TreeNode& trROI)
{
	
	if(option == IMG_RESCALE_ROI)
	{
		double dX0, dY0, dX1, dY1;//original coordinates
		m.GetXY(dX0, dY0, dX1, dY1);
		
		//double cw, ch, dw, dh;
		//get_anchor_xy_from_tree(trROI, 1, cw, ch, dw, dh);
		//
		//double dx0, dy0, dx, dy;
		//
		//dx = ((x+x0)/2*(dX1-dX0))/(rx-dX0);
		//dx0 = x+x0 - dx;
		//
		//dy = ((y+y0)/2*(dY1-dY0))/(ry-dY0);
		//dy0 = y+y0 - dy;
		double rx0, ry0, rw, rh, rx1, ry1, rx, ry;
		if(!get_anchor_xy_from_tree(trROI, 1,  rx, ry, rw, rh))
			XF_THROW(CER_INVALID_TREENODE);
		
		rx0 = rx-rw/2;
		ry0 = ry-rh/2;
		rx1 = rx+rw/2;
		ry1 = ry+rh/2;
				
		
		double dx0, dy0, dx1, dy1;//destination coordinates
		double unit_x = rw/(x1-x0);
		double unit_y = rh/(y1-y0);
		//dx0 = (unit_x*x1 + dX0 - rx)/unit_x;
		//dx1 = (unit_x*x0 + dX1 - rx0)/unit_x;
		//dy0 = (unit_y*y1 + dY0 - ry)/unit_y;
		//dy1 = (unit_y*y0 + dY1 - ry0)/unit_y;
		dx0 = x0 - (rx0 - dX0)*unit_x;
		dx1 = x1 + (dX1 - rx1)*unit_x;
		dy0 = y0 - (ry0 - dY0)*unit_y;
		dy1 = y1 + (dY1 - ry1)*unit_y;
		
		m.SetXY(dx0, dy0, dx1, dy1);
	}
	else
	{
		m.SetXY(x0, y0, x1, y1);
	}
	
	MatrixLayer ml;
	m.GetParent(ml);	
	
	remove_GraphObjects_with_prefix(ml, IMG_RESCALE_ROI_NAME);
	trROI.RemoveChildrenWithPrefix("");
}

//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 imgScale_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return imgScale_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	MatrixObject mimg;
	if(!okxf_resolve_string_get_origin_object(trGetN.m.strVal, &mimg) )	
		return false;
	
	if(!mimg.IsValid())
		return false;
	
	MatrixLayer ml;
	mimg.GetParent(ml);
	
	if(GETNE_ON_INIT == nEventID)
	{
		trGetN.trROI.Show = false;
		trGetN.SetAttribute(STR_ATTRIB_POST_USER_MESSAGE, 1);
		remove_GraphObjects_with_prefix(ml, IMG_RESCALE_ROI_NAME);
	}
	
	///Sandy 2009-3-2 this command will cause the trROI always empty in xf body, so i remove it for now, it make the xf will not close after click apply
	//if(nEventID == GETNE_ON_APPLY)
	//{
		//return PEVENT_GETN_RET_TO_CLOSE;
	//}	
	
	if(GETNE_ON_CLOSE == nEventID)
	{
		trGetN.trROI.RemoveChildrenWithPrefix("");
		remove_GraphObjects_with_prefix(ml, IMG_RESCALE_ROI_NAME);
		return true;
	}
	
	if(GETNE_ON_INIT == nEventID || !lstrcmpi(lpcszNodeName, "m") )//!lstrcmpi(lpcszNodeName, ""))
	{
		trGetN.option.nVal = 0;
		if(mimg.HasData(false))
		{
			strErrMsg = XFERR_INVALID_IMAGE;
			bOKEnable = false;
			return false;
		}
		
		int nc, nr;
		nc = mimg.GetNumCols();
		nr = mimg.GetNumRows();
		if(nr<=4||nc<=4)
		{
			strErrMsg = CERR_TOO_SMALL_MATRIX_SIZE;
			bOKEnable = false;
			return false;
		}
		
		//initialize the dimensions
		double dX0, dY0, dX1, dY1;
		mimg.GetXY(dX0, dY0, dX1, dY1);
		trGetN.x1.dVal = dX1;
		trGetN.y1.dVal = dY1;
		trGetN.x0.dVal = dX0;
		trGetN.y0.dVal = dY0;
		return true;
	
	}
	
	
	if(!lstrcmpi(lpcszNodeName, "option"))
	{
		if(trGetN.option.nVal == IMG_RESCALE_ROI)
		{	
			_init_rect(trGetN.trROI, ml);
			//save_anchors_to_tree(ml,trGetN.trROI, IMG_RESCALE_ROI_NAME);
		}
		else
		{
			_show_rect(ml, false);
	
		}
	}
	
	_show_rect(ml, trGetN.option.nVal);
	if(trGetN.option.nVal == IMG_RESCALE_ROI && GETNE_ON_GRAPH_OBJECT_CHANGE == nEventID)
	{
		save_anchors_to_tree(ml,trGetN.trROI, IMG_RESCALE_ROI_NAME);
		
		double rx0, ry0, rw, rh, rx1, ry1, rx, ry;
		get_anchor_xy_from_tree(trGetN.trROI, 1,  rx, ry, rw, rh);
		rx0 = rx-rw/2;
		ry0 = ry-rh/2;
		rx1 = rx+rw/2;
		ry1 = ry+rh/2;
		String strData;
		strData.Format("Rectangle (X0=%s X1=%s Y0=%s Y1=%s)", ftoa(rx0), ftoa(rx1), ftoa(ry0), ftoa(ry1));
		SetDataDisplayText(strData);
	}
	else
	{
		SetDataDisplayText(NULL);
	}
	
	return true;

}

int imgScale_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	string strVarName = lpcszVarName;
	
	if ( "trROI" == strVarName )
	{
		make_anchors_tree_without_info(tr);
		return 0;
	}
	return 1;
}
//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 imgScale_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 imgScale_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
