#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
//put additional include files here
#include <ReportTree.h> 

//put your own support static functions here

BOOL	plot_lineser_CreatePlots(GraphLayer& gl, DataRange& dr, TreeNode& trGetN, BOOL bFromAutoUpdate)
{
	if ( bFromAutoUpdate )
		return TRUE;
	
	if ( !gl )
		return FALSE;
	
	int	nPlot = plot_data_range(dr, gl, IDM_PLOT_UNKNOWN);
	gl.Rescale();
	
	Worksheet	wks;
	int			c1, c2;
	dr.GetRange(wks, c1, c2, 1);
	if ( !wks )
	{
		ASSERT(false);
		return FALSE;
	}
	if ( c1 < 0 && c2 < 0 )		/// no data
		return TRUE;
	
	Dataset		dsLabel(wks, c1 + 2);
	string		strDsLabel = dsLabel.GetName();
	
	AxisObject		ao = gl.XAxis.AxisObjects(AXISOBJPOS_LABEL_FIRST);
	ao.SetTypeFormatEtc(OULABEL_TEXT, strDsLabel);
	
	Tree tr;
    tr.Root.Line.Connect.nVal = dsLabel.GetSize();
    DataPlot	dp = gl.DataPlots(nPlot);
    int nRet = dp.UpdateThemeIDs(tr.Root);
    if(0==nRet)
        dp.ApplyFormat(tr, true, true);
    else
        out_str("plot settings tree construction error");
    
    gl.X.Inc = 1;
	
	return TRUE;
}

static	string	_get_err_msg_from_origin_omg(LPCSTR lpcszKey, LPCSTR lpcszSection = "General")
{
	INIFile		omg(okutil_get_origin_path(ORIGIN_PATH_SYSTEM, okutil_get_language_path()) + "origin.omg");
	return omg.ReadString(lpcszSection, lpcszKey, "");
}

#define		INVALID_ROW_INDEX		-100
typedef	struct	tagInputDataInfo
{
	InputDataInfo()
	{
		nR1 = nR2 = INVALID_ROW_INDEX;
	}
	
	Worksheet	wks;
	vector<int>	vnCols;
	int			nR1;
	int			nR2;
}INPUTDATAINFO, *LPINPUTDATAINFO;

static	bool	_is_selected_range_valid(DataRange& dr, LPINPUTDATAINFO lpstINPUTDATAINFO = NULL)
{
	int		nYColCount = 0;
		
	for ( int ii=0; ii<dr.GetNumRanges(); ++ii )
	{
		Worksheet	wks;
		int			c1, c2, r1, r2;
		dr.GetRange(ii, r1, c1, r2, c2, wks);
		for ( ; c1<=c2; ++c1 )
		{
			Column	col(wks, c1);
			if ( OKDATAOBJ_DESIGNATION_Y != col.GetType() )
				return false;
			
			if ( lpstINPUTDATAINFO )
			{
				if ( !lpstINPUTDATAINFO->wks )
					lpstINPUTDATAINFO->wks = wks;
				
				lpstINPUTDATAINFO->vnCols.Add(c1);
				
				if ( INVALID_ROW_INDEX == lpstINPUTDATAINFO->nR1 || lpstINPUTDATAINFO->nR1 > r1 )
					lpstINPUTDATAINFO->nR1 = r1;
				
				if ( r2 == -1 )
					r2 = col.GetUpperBound();
				if ( INVALID_ROW_INDEX == lpstINPUTDATAINFO->nR2 || lpstINPUTDATAINFO->nR2 < r2 )
					lpstINPUTDATAINFO->nR2 = r2;
			}
						
			++nYColCount;
		}
	}
	
	return (2 == nYColCount || 3 == nYColCount);
}

enum LINESER_RDID {
	LINESER_RDID_TABLE		= 100,
	LINESER_RDID_SERIES,
	LINESER_RDID_VALUES,
	LINESER_RDID_LABELS,
};


void plot_lineser(const Range& irng, ReportData& rd)
{
	INPUTDATAINFO	stINPUTDATAINFO;
	if ( !_is_selected_range_valid(irng, &stINPUTDATAINFO) )
	{
		ASSERT(false);
		return;
	}
	
	/// prepare intermediary data
	//int				nSize = (stINPUTDATAINFO.nR2 - stINPUTDATAINFO.nR1 + 1) * stINPUTDATAINFO.vnCols.GetSize();
	//vector			vSeries;
	//vector			vValues;
	//vSeries.SetSize(nSize);
	//vValues.SetSize(nSize);
	//
	//Column			cols[3];		/// at most 3 columns
	//vector<string>	vsLabels;
	//for ( int ii=0; ii<stINPUTDATAINFO.vnCols.GetSize(); ++ii )
	//{
		//cols[ii].Attach(stINPUTDATAINFO.wks, stINPUTDATAINFO.vnCols[ii]);
		//vsLabels.Add(cols[ii].GetLongName());
		//if ( vsLabels[ii].IsEmpty() )
			//vsLabels[ii] = cols[ii].GetName();
	//}
	//
	//int		nn = 0;
	//for ( int rr=stINPUTDATAINFO.nR1; rr<=stINPUTDATAINFO.nR2; ++rr )
	//{
		//for ( int cc=0; cc<stINPUTDATAINFO.vnCols.GetSize(); ++cc )
		//{
			//vectorbase&		vv = cols[cc].GetDataObject();
			//
			//vSeries[nn] = cc + 1;
			//vValues[nn] = vv[rr];
			//++nn;
		//}
	//}
	vector			vSeries;
	vector			vValues;
	vector<string>	vsLabels;
	stINPUTDATAINFO.wks.MakeLineSeriesData(vSeries, vValues, stINPUTDATAINFO.vnCols, stINPUTDATAINFO.nR1, stINPUTDATAINFO.nR2, &vsLabels);
	
	ReportTable rt = rd.CreateTable("LineSer", "", LINESER_RDID_TABLE);
	rt.AddColumn(vSeries, "Series", LINESER_RDID_SERIES, "Series", OKDATAOBJ_DESIGNATION_X);
	rt.AddColumn(vValues, "Values", LINESER_RDID_VALUES, "Values");
	rt.AddColumn(vsLabels, "Labels", LINESER_RDID_LABELS, "Labels", OKDATAOBJ_DESIGNATION_NONE);
}

//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 plot_lineser_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	int			nNumData = 0;
	
	DataRange	dr;
	TreeNode	trInput = trGetN.irng;
	okxf_resolve_tree_construct_range(&trInput, &dr);
	
	if ( !_is_selected_range_valid(dr) )
	{
		warning_msg_box(_get_err_msg_from_origin_omg("Only2or3YColumns"), true);
		nRet = XFEVT_ABORT;
		return;
	}
}
