#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	c_master,
	c_red,
	c_green,
	c_blue,
	c_rgb,
};

/*------------------------------------------------------------------------------*
 * Modification Log:															*
 *	Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC				*
 *------------------------------------------------------------------------------*/

#include <ReportTree.h>


#include <GetNBox.h>
#include <image_utils.h>
#include <..\Originlab\matdata_utils.h>	


//enum {
	//MASTER_CHANNEL = 0,
	//RED_CHANNEL,
	//GREED_CHANNEL,
	//BLUE_CHANNEL,
	//RGB_CHANNELS,
//};

enum _HISTOGRAM_RDID {
	_HISTOGRAM_RDID_TABLE		= 100,
	
	_HISTOGRAM_RDID_X		= IDST_FIT_X, 
	
	_HISTOGRAM_RDID_RED		= IDST_FIT_Y, 
	_HISTOGRAM_RDID_GREEN, 
	_HISTOGRAM_RDID_BLUE, 
	_HISTOGRAM_RDID_MASTER, 
	_HISTOGRAM_RDID_SINGLE, 
	
};


static void _update_report_histogram_data(ReportData& rd, const int cs, vector& vnX, vector& vnHist,
			vector& vnRHist,vector& vnGHist, vector& vnBHist)
{
	int		nDataTableID = _HISTOGRAM_RDID_TABLE;
	
	ReportTable rtHist;
	
	rtHist = rd.CreateTable("Histogram", _L("Histogram"), nDataTableID);
	rd.ID = IDST_RESULT_CURVES;

	rtHist.AddColumn(vnX, "Level", _HISTOGRAM_RDID_X, _L("Level"), OKDATAOBJ_DESIGNATION_X);
	
	switch(cs)
	{
	case c_rgb:
		rtHist.AddColumn(vnRHist, "Red", _HISTOGRAM_RDID_RED, _L("Red"), OKDATAOBJ_DESIGNATION_Y);
		rtHist.AddColumn(vnGHist, "Green", _HISTOGRAM_RDID_GREEN, _L("Green"), OKDATAOBJ_DESIGNATION_Y);
		rtHist.AddColumn(vnBHist, "Blue", _HISTOGRAM_RDID_BLUE, _L("Blue"), OKDATAOBJ_DESIGNATION_Y);
		break;

	case c_red:
		rtHist.AddColumn(vnHist, "Red", _HISTOGRAM_RDID_SINGLE, _L("Red"), OKDATAOBJ_DESIGNATION_Y);
		break;
	case c_green:
		rtHist.AddColumn(vnHist, "Green", _HISTOGRAM_RDID_SINGLE, _L("Green"), OKDATAOBJ_DESIGNATION_Y);
		break;
	case c_blue:
		rtHist.AddColumn(vnHist, "Blue", _HISTOGRAM_RDID_SINGLE, _L("Blue"), OKDATAOBJ_DESIGNATION_Y);
		break;
	case c_master:
		rtHist.AddColumn(vnHist, "Master", _HISTOGRAM_RDID_SINGLE, _L("Master"), OKDATAOBJ_DESIGNATION_Y);
		break;
	default:
		break;
	}
}

static bool _hist_rd_plotting(ReportData& rd, int cs)
{
	
	XFExeContext	*pxfexectxt = Project.GetCurrentXFExeCtxt();
	bool			bPlotEvenIfPresent = pxfexectxt->IsAddPlots();
	GraphPage	gp;
	gp = pxfexectxt->GetGraph(0);	

	
	if ( !_hist_graph(pxfexectxt, gp, 0, rd, bPlotEvenIfPresent, cs) )
		return FALSE;
	pxfexectxt->SetGraph(gp, 0);
	
	
	return true;
	
}

static bool _hist_graph(XFExeContext* pxfexectxt, GraphPage & gp, int nGraph, ReportData& rd, bool bPlotEvenIfPresent, int cs,  bool bDontCreateGraphWindIfNonexistent = false)
{
	int				nXID = _HISTOGRAM_RDID_X;
	string			strTemplate = "Origin";

	
	if ( !gp )
	{
		if ( bDontCreateGraphWindIfNonexistent )
			return TRUE;
		/// Kenny 08/25/2009 QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
		//gp.Create(strTemplate);
		gp.Create(strTemplate, CREATE_DEFAULT_OPTIONS | CREATE_ENUM_EXIST_PAGE);
		/// End QA81-14203 RESET_PAGE_NAME_IF_CREATED_FROM_OC
		
		string			strInputDesc;
		if ( pxfexectxt->GetArgDescription(strInputDesc, "x") )
		{
			string		str;
			str.Format(_L("Histogram of %s"), strInputDesc);
			gp.SetLongName(str, false);
			gp.TitleShow = WIN_TITLE_SHOW_LABEL;
		}
	}
	else if ( bPlotEvenIfPresent )
		page_load(gp, strTemplate);
	else
	{
		///Sandy 2007-7-29 REMOVE_ALL_DATAPLOTS_AND_REDRAW
		GraphLayer gl;
		gl = gp.Layers(0);
		int nPlots = gl.DataPlots.Count();
		for(int ii = 0; ii < nPlots; ii++)
		    gl.RemovePlot(0);

		//end
		//gp.Refresh(TRUE);		// just refresh
		//return TRUE;
	}
	
	GraphLayer gl;
	gl = gp.Layers(0);
	int nPlot;
	if(cs == c_rgb)
	{
		DataRange drR, drG, drB;
		
		int nYID = _HISTOGRAM_RDID_RED;
		if (1 != rd.GetDataRange(drR, _HISTOGRAM_RDID_TABLE, nXID, &nYID))
			return false;
		
		nPlot = gl.AddPlot(drR, IDM_PLOT_LINE);
		gl.DataPlots(nPlot).SetColor(1);
		
		nYID = _HISTOGRAM_RDID_GREEN;
		if (1 != rd.GetDataRange(drG, _HISTOGRAM_RDID_TABLE, nXID, &nYID))
			return false;

		nPlot = gl.AddPlot(drG, IDM_PLOT_LINE);
		gl.DataPlots(nPlot).SetColor(2);
		
		nYID = _HISTOGRAM_RDID_BLUE;
		if (1 != rd.GetDataRange(drB, _HISTOGRAM_RDID_TABLE, nXID, &nYID))
			return false;
		
		nPlot = gl.AddPlot(drB, IDM_PLOT_LINE) ;
		gl.DataPlots(nPlot).SetColor(3);
	}
	else
	{
		DataRange drPlot;
		int nYID = _HISTOGRAM_RDID_SINGLE;
		if (1 !=  rd.GetDataRange(drPlot, _HISTOGRAM_RDID_TABLE, nXID, &nYID))
			return false;
		
		nPlot = gl.AddPlot(drPlot, IDM_PLOT_LINE) ;
		//gl.DataPlots(nPlot).SetColor(0);		
		gl.DataPlots(nPlot).SetColor(cs);		
	}
	
	gl.Rescale();
	
	legend_update(gl, 4);
	LT_execute("legend -s");
	return true;
}


static bool _check_input(TreeNode& trGetN, string strErrMsg, bool& bIsGray)
{
	Image imgIn;
    if(!okxf_resolve_string_get_origin_object(trGetN.img.strVal, &imgIn) || !imgIn.IsValid())
    {
    	strErrMsg = XFERR_INVALID_IMAGE;
    	return false; 
    }
    
	pBITMAPHANDLE pLBmp = imgIn.GetLBmp();
	if(GRAY_NO != L_IsGrayScaleBitmap(pLBmp))
	{
		trGetN.c.nVal = c_master;
		bIsGray = true;
	}
	else
		bIsGray = false;
		
	return true;
}


void imgHistogram(const Image& img, const int& c, ReportData& rd, const int& plot)
{
	
	pBITMAPHANDLE phBmp = img.GetLBmp();
	int nLen=get_image_data_max_val(phBmp)+1;
	
	vector<int> vnHist;
	vector<int> vnRHist;
	vector<int> vnGHist;
	vector<int> vnBHist;
	
	int nRet;
	if(c!=c_rgb)//single channel
	{
		//	vnHist.SetSize(256);	
		vnHist.SetSize(nLen);
		nRet = histogram_image(phBmp, vnHist, nLen ,c);
		
	
	}
	else//multi-channels
	{
		//	vnRHist.SetSize(256);
		vnRHist.SetSize(nLen);
		nRet = histogram_image(phBmp, vnRHist, nLen ,c_red);
		//	vnGHist.SetSize(256);
		vnGHist.SetSize(nLen);
		nRet = histogram_image(phBmp, vnGHist, nLen ,c_green);
		//	vnBHist.SetSize(256);
		vnBHist.SetSize(nLen);
		nRet = histogram_image(phBmp, vnBHist, nLen ,c_blue);
	
	}
	
	if(nRet < MAX_ERROR_CODE_FROM_LT)
		XF_THROW_EX(XFERR_LEADTOOLS_FUNCTION_UNKNOWN_ERR, nRet);
	
	if(nRet !=  SUCCESS)
		XF_THROW(nRet);
	
	vector vX;
	//	vX.Data(0,256-1,1);
	vX.Data(0,nLen-1,1);
	vector vHist, vR, vG, vB;
	vHist = vnHist;
	vR = vnRHist;
	vG = vnGHist;
	vB = vnBHist;
	
	_update_report_histogram_data(rd, c, vX, vHist, vR, vG, vB);
	
	if(plot)
		_hist_rd_plotting(rd, c);
	
}

//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 imgHistogram_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return imgHistogram_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	
	bool bIsGray;		
	bOKEnable =  _check_input(trGetN, strErrMsg, bIsGray);	
	if(!bOKEnable)
	{
		strErrMsg = XFERR_INVALID_IMAGE;
		return true;
	}
	string strValChange = lpcszNodeName;
	if(nEventID == GETNE_ON_INIT || strValChange == "img")
	{
	
		if(bIsGray == false)
		{
			trGetN.c.SetAttribute(STR_COMBO_ATTRIB,"Master|Red|Green|Blue|RGB");
	
		}	  
		else
		{
			trGetN.c.Show = false;
		}
	
	}
	
	return true;
	

}

int imgHistogram_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 imgHistogram_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if ( (dwCntrl&LTXF_THEME_USED) && nGetNDialog <= 0 )
	{
		string strErrMsg;
		bool bIsGray;
		if ( true != _check_input(trGetN, strErrMsg, bIsGray) )
			nRet = XFEVT_PROCEED_WITH_DLG;
	}
}
//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 imgHistogram_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
