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

/////////////////////////////////////////////////////////////
// Modification log
//
//
// CPY 9/24/08 QA70-92268 GR_SHOULD_ALLOW_ON_MULTI_LAYER_GRAPH
// Fisher 7/20/09 QA70-13575 HANDLE_RESCALE_EVENT_FOR_GRAPH_OBJ_TOOL
// Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
// Kyle 02/11/2010 QA80-15104-P1 REMOVE_PREVIEW_CURVE_IF_NO_DATA_SELECTED
// Sophy 2/22/2010 QA80-15137 ROI_FFT_LABEL_MISSED_WHEN_RELOAD_OPJ
/////////////////////////////////////////////////////////////

#include <..\originlab\grobj_utils.h>
#include <..\originlab\GraphObjTools.h>
#include <fft_utils.h>
#include <o8dlg.h>

#define XF_NAME		"addtool_curve_fft"
#define	TOOLNAME	_L("Gadget FFT")
#define	TOOL_PREFERENCES_TITLE	_L("FFT")
///Sophy 1/19/2010 SHOW_TOOLNAME_FOR_ROI_TOOLS
#define	NEW_ID_BEGIN	(GET_USER_DATAID(0) + 10)
enum FFT_NEW_NODE_ID{
	FFT_TOOLNAME_ID = NEW_ID_BEGIN,
};
///end SHOW_TOOLNAME_FOR_ROI_TOOLS

class FFTCurveTool : public GraphObjCurveTool
{
	
public:
	FFTCurveTool(LPCSTR lpcszMainObjName = NULL) : GraphObjCurveTool(lpcszMainObjName)
	{
		m_strPreviewDataWksName = "TmpBkFFT";
		m_strPreviewDataWksLongName = "FFT Tool Data";
		
		m_strGraphTemplate = "FFTPREVIEW";
		m_strPreviewGraphLongName = "FFT Tool Spectrum Display";
	}	
	
	//---- CPY 9/26/08 QA70-12266 ADDTOOL_XF_NEEDS_PROJ_VAR_TO_INDICATE_THEY_ARE_STILL_ACTIVE
protected:
	//virtaul
	string GetSignature() // convention, "xf_xfname", this is the name to create project variable
	{
		return "xf_" XF_NAME;
	}
	//----
	
	///Sophy 1/7/2010 QA80-14904-S1 CLEAN_CODE_FOR_ROI_TOOLS
	//virtual
	string GetXFName(){ return XF_NAME; }
	///end CLEAN_CODE_FOR_ROI_TOOLS
	
	//virtual 
	BOOL OnMove()
	{
		if( !OnPreMove() )
			return false;
		
		if(!GetData())
		{
			///Kyle 02/11/2010 QA80-15104-P1 REMOVE_PREVIEW_CURVE_IF_NO_DATA_SELECTED
			ConnectToTempPreviewDataAndGraph();
			if( m_wks )
				m_wks.SetSize(0, -1);
			if( m_glPreview )
			{
				GraphPage gp = m_glPreview.GetPage();
				gp.Refresh();
			}
			///End REMOVE_PREVIEW_CURVE_IF_NO_DATA_SELECTED
			return true; // no data, nothing to do, not an error
		}
		///Sophy 2/22/2010 QA80-15137 ROI_FFT_LABEL_MISSED_WHEN_RELOAD_OPJ
		//UpdateTopLabel("", false);	///Sophy 1/25/2010 SHOW_WARNING_ON_NOT_GETTTING_ENOUGH_DATA_POINT if has valid data, should clear error message
		UpdateTopLabel("No Message", false);	///Sophy 1/25/2010 SHOW_WARNING_ON_NOT_GETTTING_ENOUGH_DATA_POINT if has valid data, should clear error message
		///end ROI_FFT_LABEL_MISSED_WHEN_RELOAD_OPJ
		///Sophy 2/2/2010 FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		//DataRange dr;
		//m_dp.GetDataRange(dr, m_i1, m_i2);
		///end FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		BOOL bFirstTime = false; //----------- CPY 9/23/08 QA70-12265 RESCALE_NOT_WORKING_IN_FFT_PREVIEW
		if(CheckShowPreview() > 0)// shown first time, check rescale checkbox in template
		{
			bFirstTime = true; //----------- CPY 9/23/08 QA70-12265 RESCALE_NOT_WORKING_IN_FFT_PREVIEW
			m_wks.SetSize(-1, 2);
			DataRange dr;
			dr.Add(m_wks, 0, "X");
			dr.Add(m_wks, 1, "Y");
			m_glPreview.AddPlot(dr, IDM_PLOT_LINE);
		}
		m_strRescaleCheckBoxName = GetPreviewGraphName() + "!fftoptions.rescale";
		if(bFirstTime)
			LT_set_var(m_strRescaleCheckBoxName, 1);
				
		///Sophy 2/2/2010 FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		//curve_fft(dr);
		quick_curve_fft();
		///end FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		return GraphObjCurveTool::OnMove();
	}
	
	/// Fisher 7/20/09 QA70-13575 HANDLE_RESCALE_EVENT_FOR_GRAPH_OBJ_TOOL
	// on rescale, we simply clear the data
	// virtual
	///Sophy 12/3/2009 QA80-14686 CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
	//BOOL OnRescale()
	BOOL InvalidateResults()
	///end CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH
	{
		//---- CPY 7/20/09 QA70-13575 HANDLE_RESCALE_EVENT_FOR_GRAPH_OBJ_TOOL
		//CheckPreviewDataWks(); 
		//
		//if(m_wks)
		//	m_wks.Destroy();
		if(CheckPreviewDataWks(false) < 0)
			return true;
		if(m_wks)
		{
			m_wks.ClearData();
		}
		//----
		OnMove(); ///Sophy 12/3/2009 QA80-14686 CENTRALIZE_CODE_FOR_UPDATE_RESULT_ON_RESCALE_GRAPH OnRescale should also update preview graph
		return TRUE;
	}
	/// End HANDLE_RESCALE_EVENT_FOR_GRAPH_OBJ_TOOL	
	
	//virtual
	int		CreateAttachments()
	{
		int nRet = GraphObjCurveTool::CreateAttachments();
		if ( 0 != nRet )
			return nRet;
		///Sophy 2/22/2010 QA80-15137 ROI_FFT_LABEL_MISSED_WHEN_RELOAD_OPJ
		//m_goLabel.Show = false; //FFT dont need to show this label currently.
		UpdateTopLabel("No Message", false); //FFT dont need to show this label currently.
		///end ROI_FFT_LABEL_MISSED_WHEN_RELOAD_OPJ
		return nRet;
	}
	
	//virtual
	bool	UpdateContextMenu(Menu& pm, uint& nPosition)
	{
		RemoveMenu(pm, nPosition); //remove output menu item
		RemoveMenu(pm, nPosition);	///Sophy 1/26/2010 ADD_GO_TO_REPORT_TABLE_MENU_IN_CONTEXT remove "Go to Report"
		RemoveMenu(pm, nPosition); //remove separator after output menu item
		return true;
	}
	
	//virtual
	string	GetToolName(){ return TOOLNAME; }
	//virtual
	string	GetPreferenceTitle(){ return TOOL_PREFERENCES_TITLE; }
		
private:
	///Sophy 2/2/2010 FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
	//void curve_fft(const DataRange& drs)
	void	quick_curve_fft()
	///end FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
	{
		if ( !m_wks )
			return;//CPY when have not setup the fft framework yet, so better ignores it
		
		///Sophy 2/2/2010 FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		//DWORD dwPlotID;
		//vector vy, vx, vfreq, vAmp;
		//if(drs.GetData(DRR_GET_MISSING |  DRR_GET_DEPENDENT | DRR_NO_FACTORS, 0, &dwPlotID, NULL, &vy, &vx) < 0)
			//return;
		///Sophy 5/4/2010 QA82-15364-P2 ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS
		//vector vX, vY, vFreq, vAmp;
		//if ( m_dp.GetDataPoints(m_i1, m_i2, vX, vY) <= 0 )
			//return;
		/////end FAIL_TO_GET_DATA_WHEN_SRC_X_IS_NOT_NUMERIC
		//
		//int nSize = vX.GetSize();
		//int nSizeH = nSize/2;
		//
		//fft_amp(vX, vY, vFreq, vAmp, nSize, true);
		vector vFreq, vAmp;
		fft_amp(m_vX, m_vY, vFreq, vAmp, m_vX.GetSize(), true);
		///end ROI_TOOLS_OPTION_FOR_SKIP_ALL_MASKED_DATAPOINTS
		if(m_wks.GetNumCols() < 2)
		{
			ASSERT(false);
			m_wks.SetSize(-1, 2);
		}
		Dataset dx(m_wks, 0);
		dx = vFreq;
		Dataset dy(m_wks, 1);
		dy = vAmp;
		
		checkRescale();
	}
	checkRescale()
	{
		double dd;
		LT_get_var(m_strRescaleCheckBoxName, &dd);
		if(dd > 0)
			m_glPreview.Rescale();		
	}
private:
	string m_strRescaleCheckBoxName;
	
};

//XF_NAME_events
void addtool_curve_fft_events(string strGrName, int nEvent, int nMsg = 0)
{
	FFTCurveTool gtool;
	///Sophy 1/7/2010 QA80-14904-S1 CLEAN_CODE_FOR_ROI_TOOLS
	//gtool.OnEvent(nEvent);	
	graphobjtool_events(gtool, strGrName, nEvent, nMsg);
	///end CLEAN_CODE_FOR_ROI_TOOLS
}




void addtool_curve_fft(const TreeNode& trGUI)
{
	
	FFTCurveTool gtool;
	///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	//int nErr = gtool.Create(XF_NAME, color);
	int nErr = gtool.Create(XF_NAME, 0, trGUI);
	///end CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	if(nErr < 0)
	{
		XF_THROW(XFERR_INVALID_GRAPH_LAYER);
		return;
	}
	if(nErr != 0)
		error_report("addtool_curve_fft failed to init");
	
	
}

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

}

int addtool_curve_fft_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	if ( tr.IsValid() )
	{
		string strVarName(lpcszVarName);
		if ( strVarName == "trGUI" )
		{
			int nUserID = GET_USER_DATAID(0);
			GETN_USE(tr) GETN_OPTION_BRANCH(GETNBRANCH_OPEN)
			GETN_STR(toolname, STR_TOOLNAME, TOOLNAME)	GETN_ID(FFT_TOOLNAME_ID)	GETN_CONTROL_OPTION_BOX(0)	///Sophy 1/19/2010 SHOW_TOOLNAME_FOR_ROI_TOOLS
			///Sophy 8/21/2009 QA80-14175 CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
			GETN_COLOR(rectcolor, STR_FILL_COLOR, 20)	GETN_COLOR_CHOICE_OPTIONS(COLORLIST_CUSTOM | COLORLIST_SINGLE) GETN_ID(nUserID++)
			///end CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
		}
	}
	///end CREATE_ALL_NODES_IN_ONE_TREE_TO_GET_RID_OF_OPTIONS_BRANCH
	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 addtool_curve_fft_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	if ( is_xf_startup(nGetNDialog, dwCntrl) )
	{
		if(is_use_origin_chm())
			trGetN.SetAttribute(STR_HELPID_ATTRIB, IDD_XF_addtool_curve_fft);
	}
}
//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 addtool_curve_fft_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
