#ifndef _IMG_ROI_PREVIEW_H
#define _IMG_ROI_PREVIEW_H

///Sandy 2007-3-12 move to grobj_utils.h/cpp
//#define IDE_ANCHOR_NUMBER			    1000
//#define IDE_ANCHOR_ID     				2000
//
//#define IDE_ATTR_BIT_ANCHOR_NAME   		10
//#define IDE_ATTR_BIT_ANCHOR_TYPE  		20
//#define IDE_ATTR_BIT_ANCHOR_X			30
//#define IDE_ATTR_BIT_ANCHOR_Y	  		40
//#define IDE_ATTR_BIT_ANCHOR_W   		50
//#define IDE_ATTR_BIT_ANCHOR_H   		60
//
//#define ATTACH_TO_SCALE 2
//
//bool make_anchors_tree_without_info(TreeNode& tr, int nAnchorsNum = 1)
//{
	//
	//if(!tr.IsValid())
		//return false;
	//
	//for(int ii = 0; ii<nAnchorsNum;ii++)
	//{
		//TreeNode trAnchor;
		//int nID = IDE_ANCHOR_ID + ii + 1;
		//tree_check_get_node_by_dataid(tr, trAnchor, "Anchor"+(string)(ii+1), nID);
		//
		//TreeNode trAnchorName, trAnchorType, trAnchorX, trAnchorY, trAnchorW, trAnchorH;
		//tree_check_get_node_by_dataid(trAnchor, trAnchorName, "Name", nID+IDE_ATTR_BIT_ANCHOR_NAME);
		//tree_check_get_node_by_dataid(trAnchor, trAnchorType, "Type", nID+IDE_ATTR_BIT_ANCHOR_TYPE);
		//tree_check_get_node_by_dataid(trAnchor, trAnchorX, "X", nID+IDE_ATTR_BIT_ANCHOR_X);
		//tree_check_get_node_by_dataid(trAnchor, trAnchorY, "Y", nID+IDE_ATTR_BIT_ANCHOR_Y);
		//tree_check_get_node_by_dataid(trAnchor, trAnchorW, "Width", nID+IDE_ATTR_BIT_ANCHOR_W);
		//tree_check_get_node_by_dataid(trAnchor, trAnchorH, "Height", nID+IDE_ATTR_BIT_ANCHOR_H);
//
	//}
	//
	//TreeNode trNum;
	//tree_check_get_node_by_dataid(tr, trNum,"Number", IDE_ANCHOR_NUMBER);
	//
	//return true;	
//
//}
////#include <..\originlab\ImgChannelData.h>
//static vector<int> s_vnObjectType = {GROT_ELLIPSE,GROT_RECT};
//
//bool get_anchor_xy_from_tree(TreeNode& trAnchors, int nIndex,  double& x0, double& y0, double& w, double& h)
//{
	//if(!trAnchors.IsValid()||nIndex<=0)
		//return false;
	//
	//TreeNode trNum = tree_find_node_by_dataID(trAnchors, IDE_ANCHOR_NUMBER);
	//if(!trNum.IsValid() || trNum.nVal == 0 || nIndex > trNum.nVal)
		//return false;
//
	//int nID = IDE_ANCHOR_ID + nIndex;
	//TreeNode trAnchor = tree_find_node_by_dataID(trAnchors, nID);
	//if(!trAnchor.IsValid())
		//return false;
	//
	//TreeNode trAnchorName = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_NAME);
	//TreeNode trAnchorType = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_TYPE);
	//TreeNode trAnchorX = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_X);
	//TreeNode trAnchorY = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_Y);
	//TreeNode trAnchorW = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_W);
	//TreeNode trAnchorH = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_H);
	//
	//if(!trAnchorName.IsValid()||!trAnchorType.IsValid()||!trAnchorX.IsValid()
		//||!trAnchorY.IsValid()||!trAnchorW.IsValid()||!trAnchorH.IsValid())
	//{
		//return false;
	//}
	//
	//w = trAnchorW.dVal;
	//h = trAnchorH.dVal;
	//x0 = trAnchorX.dVal;
	//y0 = trAnchorY.dVal;
	//
	//return true;	
	//
//}
//
//bool update_tree_anchors_object_type(int nObjectType, TreeNode& trAnchors)
//{
	//if(!trAnchors.IsValid())
		//return false;
	//
	//TreeNode trNum = tree_find_node_by_dataID(trAnchors, IDE_ANCHOR_NUMBER);
	//if(!trNum.IsValid())
		//return false;
	//int nNumAnchors = trNum.nVal;
	//
	//for(int ii = 1; ii<=nNumAnchors; ii++)
	//{
		//TreeNode& trAnchor = trAnchors.GetNode("Anchor"+(string)ii);
		//if(!trAnchor.IsValid())
			//return false;	
		//
		//TreeNode& trAnchorType = trAnchor.GetNode("Type");
		//if(!trAnchorType.IsValid() || trAnchorType.nVal ==  nObjectType)
			//return false;
		//
		//
		//trAnchorType.nVal = nObjectType;
	//}
	//return true;
//}
//
//bool save_anchors_to_tree(Layer& lay, TreeNode& tr, LPCSTR lpcstrPrefix)
//{
	//
	//if(!lay.IsValid()||!tr.IsValid())
		//return false;
	//
	//int nNumAnchors = 0;
	//foreach(GraphObject go in lay.GraphObjects)
	//{
		//string str = go.GetName();
		//if(0 == strncmp(str, lpcstrPrefix, strlen(lpcstrPrefix)))
		//{
			//nNumAnchors++;
			//TreeNode trAnchor;
			//int nID = IDE_ANCHOR_ID + nNumAnchors;
			//tree_check_get_node_by_dataid(tr, trAnchor, "Anchor"+(string)(nNumAnchors), nID);
			//
			//TreeNode trAnchorName, trAnchorType, trAnchorX, trAnchorY, trAnchorW, trAnchorH;
			//tree_check_get_node_by_dataid(trAnchor, trAnchorName, "Name", nID+IDE_ATTR_BIT_ANCHOR_NAME);
			//tree_check_get_node_by_dataid(trAnchor, trAnchorType, "Type", nID+IDE_ATTR_BIT_ANCHOR_TYPE);
			//tree_check_get_node_by_dataid(trAnchor, trAnchorX, "X", nID+IDE_ATTR_BIT_ANCHOR_X);
			//tree_check_get_node_by_dataid(trAnchor, trAnchorY, "Y", nID+IDE_ATTR_BIT_ANCHOR_Y);
			//tree_check_get_node_by_dataid(trAnchor, trAnchorW, "Width", nID+IDE_ATTR_BIT_ANCHOR_W);
			//tree_check_get_node_by_dataid(trAnchor, trAnchorH, "Height", nID+IDE_ATTR_BIT_ANCHOR_H);
			//
			//trAnchorName.strVal = str;
			//int nType;
			//go.GetObjectType(&nType);
			//trAnchorType.nVal = nType;
			//trAnchorX.dVal = go.X;
			//trAnchorY.dVal = go.Y;
			//double dw, dh;
			//get_go_size(go, &dw, &dh);
			//trAnchorW.dVal = dw;
			//trAnchorH.dVal = dh;			
			//
			//
		//}
	//}
	//
	//TreeNode trNum;
	//tree_check_get_node_by_dataid(tr, trNum,"Number", IDE_ANCHOR_NUMBER);
	//trNum.nVal = nNumAnchors;
	//
	//return true;	
//
//}
//
//
//bool read_and_create_anchors_from_tree(Layer& lay, TreeNode& tr, LPCSTR lpcstrPrefix, GraphObject& go = NULL)
//{
//
	//if(!lay.IsValid()||!tr.IsValid())
		//return false;
		//
	//TreeNode trNum = tree_find_node_by_dataID(tr, IDE_ANCHOR_NUMBER);
	//if(!trNum.IsValid() || trNum.nVal == 0)
		//return false;
	//
	//int nNumAnchors = trNum.nVal;
	//
	//for(int ii = 1; ii<=nNumAnchors; ii++)
	//{
		//int nID = IDE_ANCHOR_ID + ii;
		//TreeNode trAnchor = tree_find_node_by_dataID(tr, nID);
		//if(!trAnchor.IsValid())
			//return false;
		//
		//TreeNode trAnchorName = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_NAME);
		//TreeNode trAnchorType = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_TYPE);
		//TreeNode trAnchorX = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_X);
		//TreeNode trAnchorY = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_Y);
		//TreeNode trAnchorW = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_W);
		//TreeNode trAnchorH = tree_find_node_by_dataID(trAnchor, nID+IDE_ATTR_BIT_ANCHOR_H);
		//
		//if(!trAnchorName.IsValid()||!trAnchorType.IsValid()||!trAnchorX.IsValid()
			//||!trAnchorY.IsValid()||!trAnchorW.IsValid()||!trAnchorH.IsValid())
		//{
			//return false;
		//}
		//
		//int nHalfW = trAnchorW.dVal/2;
		//int nHalfH = trAnchorH.dVal/2;
		//int nX = trAnchorX.dVal;
		//int nY = trAnchorY.dVal;
		//
		//GraphObject goTemp;
		//if(trAnchorType.nVal == GROT_ELLIPSE)
		//{
			//if( !add_ellipse(lay, goTemp, nX-nHalfW, nY-nHalfH, nX+nHalfW, nY+nHalfH, INDEX_COLOR_TRANSPARENT,  ATTACH_TO_SCALE,  false) )
				//return false;			
		//}
		//else if(trAnchorType.nVal == GROT_RECT)
		//{
			//if( !add_rect(lay, goTemp, nX-nHalfW, nY-nHalfH, nX+nHalfW, nY+nHalfH, INDEX_COLOR_TRANSPARENT,  ATTACH_TO_SCALE, LN_FREE, false,  false) )
				//return false;			
		//}
		//
		//goTemp.SetName(trAnchorName.strVal);
		//if(go != NULL)
			//go = goTemp;
		//
		////set_go_border_color(go, SYSCOLOR_GREEN);
		////set_LT_script(go, "events_from_img2xyz_go;" , GRCT_SIZEMOVE);	
		//
	//}
	//return true;
//}
//
static vector<int> s_vnObjectType = {GROT_ELLIPSE,GROT_RECT};
class OCImgROIPreview
{
public:
	//separate color channel and create temp data Matrix and Preview Graph 
	OCImgROIPreview(MatrixObject& mobj,  LPCSTR lpcstrPreviewPage, int dsType = EXIST_MATRIX, LPCSTR lpcstrChannel = "Intensity");
	~OCImgROIPreview();
	
	virtual bool SetupGraphPreview();

	bool GetChannelMatrix(MatrixObject& mo, const string& strChannelName);
	

private:
	int separateChannelData(vector<string>& vsChannelName);
	
protected:
	MatrixPage   m_mpParent;
	MatrixLayer  m_mlParent;
	MatrixObject m_moSrcImage;
	MatrixLayer  m_mlChannelData;
	MatrixObject m_moIntensity;

	Page         m_pTempData;
	Datasheet    m_dsTempData;
	
	GraphPage    m_gpPreview;
	
	int 		 m_nCols;
	int 		 m_nRows;
	
	//string       m_strInstance;
	

};


//////////////////////////member functions///////////////////////////////////
int OCImgROIPreview::separateChannelData(vector<string>& vsChannelName)
{
	int nChannel = -1;
	m_mlChannelData.SetSize(5, m_nRows, m_nCols);

	
	vector<string> vsName = {"Intensity", "Red", "Green", "Blue"};
	for ( int ii = 0; ii < vsChannelName.GetSize(); ii++ )
		vsName[ii] = vsChannelName[ii];
	
	MatrixObject& mIntensity = m_mlChannelData.MatrixObjects(0);
	MatrixObject& mRed = m_mlChannelData.MatrixObjects(1);
	MatrixObject& mGreen = m_mlChannelData.MatrixObjects(2);
	MatrixObject& mBlue = m_mlChannelData.MatrixObjects(3);
	MatrixObject& mRGB = m_mlChannelData.MatrixObjects(4);
	
	
	mIntensity.SetLongName(vsName[0]);
	mRed.SetLongName(vsName[1]);
	mGreen.SetLongName(vsName[2]);
	mBlue.SetLongName(vsName[3]);
	mRGB.SetLongName("RGB");
	
	if(!matobj_copy(mRGB,m_moSrcImage))
	{
		return -1;
	}

	Image imgRGB(mRGB);
	Image imgR(mRed);
	Image imgG(mGreen);
	Image imgB(mBlue);
	
	
	BITMAPHANDLE* pLBmp = imgRGB.GetLBmp();
	
	if(GRAY_NO == L_IsGrayScaleBitmap(pLBmp))
	{
		if(SUCCESS != image_split_rgb(imgRGB, imgR, imgG, imgB))
			return -1;
		

		///sandy 2007-5-4 update code for Image::CopyTo()
		//if(SUCCESS != L_GrayScaleBitmap(pLBmp, 8))
			//return -1;		
		
		//imgRGB.CopyTo(mIntensity, true);
		//imgR.CopyTo(mRed, true);
		//imgG.CopyTo(mGreen, true);
		//imgB.CopyTo(mBlue, true);		
		
		///Sandy 2007-7-18 for some color image less than 8 bit color
		//int bits = pLBmp->BitsPerPixel/3;
		int bits;
		if(pLBmp->BitsPerPixel <= 8)
			bits = 8;
		else
		    bits = pLBmp->BitsPerPixel/3;
		//end
		
		if(SUCCESS != L_GrayScaleBitmap(pLBmp, bits))
			return -1;
		
		imgRGB.CopyTo(mIntensity, true, bits);
		imgR.CopyTo(mRed, true, bits);
		imgG.CopyTo(mGreen, true, bits);
		imgB.CopyTo(mBlue, true, bits);
		
		//end 2007-5-4
		


		nChannel = 4;
	}
	else
	{
		matrixbase& matbase = m_moSrcImage.GetDataObject();
		matrixbase& mat = mIntensity.GetDataObject();
		mat = matbase;
		nChannel = 1;
	}


	mIntensity.SetInternalData(FSI_DOUBLE);
	mRed.SetInternalData(FSI_DOUBLE);	
	mGreen.SetInternalData(FSI_DOUBLE);	
	mBlue.SetInternalData(FSI_DOUBLE);	
	
	return nChannel;
}

bool OCImgROIPreview::GetChannelMatrix(MatrixObject& mo, const string& strChannelName)
{

	mo = m_mlChannelData.FindCol(strChannelName);
	
	if ( !mo.IsValid() )
		return false;
	return true;

}

void OCImgROIPreview::OCImgROIPreview(MatrixObject& mobj,  LPCSTR lpcstrPreviewPage, int dsType, LPCSTR lpcstrChannel)
{
	m_moSrcImage = mobj;

	mobj.GetParent(m_mlParent);
	m_mpParent = m_mlParent.GetPage();
	
	m_nCols = m_moSrcImage.GetNumCols();
	m_nRows = m_moSrcImage.GetNumRows();	
	
	if(dsType == EXIST_MATRIX)
	{
		MatrixPage mpData(lpcstrPreviewPage);
		if(!mpData.IsValid())
		{
			mpData.Create("Origin", CREATE_HIDDEN|CREATE_SET_MISSING_IN_MANAGER );
			mpData.Rename(lpcstrPreviewPage);
		}
		m_dsTempData = mpData.Layers(0);
		m_pTempData = mpData;

	}
	else if(dsType == EXIST_WKS)
	{
		WorksheetPage wpData(lpcstrPreviewPage);
		if(!wpData.IsValid())
		{
			wpData.Create("Origin", CREATE_HIDDEN|CREATE_SET_MISSING_IN_MANAGER );
			wpData.Rename(lpcstrPreviewPage);
		}
		m_dsTempData = wpData.Layers(0);
		m_pTempData = wpData;
	}
	
	GraphPage gpPreview();
	if(!gpPreview.IsValid())
	{
		gpPreview.Create("Origin");
		gpPreview.Rename(lpcstrPreviewPage);
		
		gpPreview.SetLongName("Preview");
		gpPreview.TitleShow = WIN_TITLE_SHOW_BOTH;
	}
	m_gpPreview = gpPreview;
	
	
	int nLayer = m_mpParent.AddLayer(lpcstrPreviewPage);
	m_mlChannelData = m_mpParent.Layers(nLayer); 
	
	if(m_moSrcImage.HasData(false))
	{
		m_moSrcImage.SetXY(0, 0 , m_nCols,m_nRows );
		m_mlParent.SetViewImage();
		m_mlChannelData.SetSize(1, m_nRows, m_nCols);
		MatrixObject& mIntensity = m_mlChannelData.MatrixObjects(0);
		
		matrixbase& matbase = m_moSrcImage.GetDataObject();
		matrixbase& mat = mIntensity.GetDataObject();
		mat = matbase;
		
		mIntensity.SetInternalData(FSI_DOUBLE);
	}
	else
	{
		vector<string> vsChannelName = {"Intensity", "Red", "Green", "Blue"};
		separateChannelData(vsChannelName);
	}
	
	m_moIntensity = m_mlChannelData.MatrixObjects(0);	
	
	m_mpParent.Show();
}

void OCImgROIPreview::~OCImgROIPreview()
{

	if(m_pTempData.IsValid())
		m_pTempData.Destroy();
	
	if(m_mlChannelData.IsValid())
		m_mlChannelData.Destroy();
	
	if(m_gpPreview.IsValid())
		m_gpPreview.Destroy();
}



//bool OCImgROIPreview::extractIntensity()
//{
	//imgChannelData   chnlData;
	//
	//chnlData.SeparateChannelData(m_moSrcImage, vsChannelName);
	//chnlData.GetChannelMatrix(m_moIntensity,vsChannelName[0]);
	//return true;
//}

#endif //_IMG_ROI_PREVIEW_H