#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>

/// RVD 1/23/2009 QA80-13011 PA_MARKER_ACTIVATION
/// Jasmine 02/19/09 QA80-13131 PRESS_ENTER_TO_CLOSE_GRAPHDONEDLG

//put additional include files here
#include <xfGraph_utils.h>
#include <..\OriginLab\PAWizCore.h>


#define	OE_SELECT_MARKER_HANDLE	 (OE_USER+1)	/// RVD 1/23/2009 QA80-13011 PA_MARKER_ACTIVATION

///Jasmine 02/19/09 QA80-13131 PRESS_ENTER_TO_CLOSE_GRAPHDONEDLG
typedef bool (*FUNC_CLOSE_GRAPH_DONE_WND)(DWORD dwDlg);
///End PRESS_ENTER_TO_CLOSE_GRAPHDONEDLG

static int  _get_context_from_user_info(TreeNode trUserInfo)
{
    int nContext = MDC_BASELINE;
    if( NULL != trUserInfo && trUserInfo.IsValid() )
    {
    	TreeNode trContext = trUserInfo.GetNode(PA_MODIFY_DELETE_CONTEXT_TAGNAME);
    	if(trContext)
    		nContext = trContext.nVal;
    }
    return nContext;
}


class ModifyBaselineMarkers : public CurveMarkers
{
	
protected:
	bool GetSettings()
	{
		return false;
	}
public:
	ModifyBaselineMarkers(MarkerInfo& mi) : CurveMarkers(mi)
	{
	}
	//virtual 
	bool OnInit(MarkerInfo& mi)
	{
		/// RVD 1/23/2009 QA80-13011 PA_MARKER_ACTIVATION
		OriginObject oo;
		mi.GetParent(oo);
		oo.PostMessage(OE_SELECT_MARKER_HANDLE);
		/// end PA_MARKER_ACTIVATION
	
		vector vx, vy;
		if(!get_plot_data_xy(m_dp, vx, vy))
		{
			throw(XFERR_GET_DATA_FAILED);
		}

		m_dp.SetActive();
		return InitXY(mi, vx, vy);
	}

	///Sandy 2008-10-13 QA80-12366 ADD_USER_INFO_TREE_ON_EDIT
	//bool OnEdit(int nMkIndex, MarkerInfo& mi)
	bool OnEdit(int nMkIndex,  TreeNode& trUserInfo, MarkerInfo& mi)
	{
		if(!IsValid())
			return false;
		
 		vector vxMI, vyMI;	
		vxMI = m_trMI.Data.X.dVals;
		vyMI = m_trMI.Data.Y.dVals;
		
	    string  strData;
		strData.Format("X:%s, Y:%s", ftoa(vxMI[nMkIndex]), ftoa(vyMI[nMkIndex]));
		SetDataDisplayText(strData);

		//vector<uint> vnIndex;
	    //vxMI.Sort(SORT_ASCENDING, TRUE, vnIndex);
	    //vyMI.Reorder(vnIndex);
	    
	    ///Sandy 2008-4-23 expand usage to OnEdit(), maybe roman should add trUserInfo to OnEdit as well
	    //TreeNode tr = GetUserData();//wrong solution, wait for roman again.
	    int nContext =  _get_context_from_user_info(trUserInfo);
	    
	    
	    if(MDC_BASELINE == nContext)
	    {
	    	sortAnchorsByXAscending(vxMI, vyMI);
	    }

	    if( MDC_BASELINE == nContext ||  MDC_PEAKS == nContext )
	    {
			DataRange dr;
			if (!m_dp.GetDataRange(dr) || !dr.SetData(&vyMI, &vxMI))
			{
				error_report("OnEdit::fail in update data of anchor range ");
			}
			post_getn_dialog_message(WM_USER_ON_GRAPH_OBJECT_CHANGE, nMkIndex);
			return true;
		}
		
		//doing not finish
		/*
		else if( MDC_FITPEAKS == nContext)
		{
			XYRange oy;
			pa8_check_get_peak_temp_range(oy);
			if ( !oy.IsValid() )
				return false;


			oy.SetData(&vyMI, &vxMI, 0, NULL, 0);
			
			Page pg = Project.Pages();
			if(pg)
			{
				vector<string> vsFunctions;
				vector<int> vnNeedUpdate;
				pa8_get_pa_fit_change_peaks(pg, vsFunctions, vnNeedUpdate);
				vnNeedUpdate[nMkIndex] = 1;
				vsFunctions.Reorder(vnIndex);
				vnNeedUpdate.Reorder(vnIndex);
				pa8_save_pa_fit_change_peaks(pg, vsFunctions, vnNeedUpdate);
			}
			
			post_getn_dialog_message(WM_USER_ON_GRAPH_OBJECT_CHANGE, nMkIndex);
			return true;
		}
		*/

		return false;
	}
	
	bool OnDelPart(int nMkIndex, TreeNode& trUserInfo, MarkerInfo& mi)
	{
		if(!IsValid())
			return false;
		
		vector vxMI, vyMI;	
		vxMI = m_trMI.Data.X.dVals;
		vyMI = m_trMI.Data.Y.dVals;
	
		if( vxMI.GetSize() > nMkIndex )
		{
			vxMI.RemoveAt(nMkIndex);
			vyMI.RemoveAt(nMkIndex);
		}

	    int nContext =  _get_context_from_user_info(trUserInfo);
 
	    
	    if( MDC_BASELINE == nContext )
	    {
	    	sortAnchorsByXAscending(vxMI, vyMI);
			DataRange dr;
			if (!m_dp.GetDataRange(dr) || !dr.SetData(&vyMI, &vxMI))
			{
				error_report("OnDelPart::fail in update data of anchor range ");
			}
		}
		else if( MDC_PEAKS == nContext ||  MDC_FITPEAKS == nContext)
		{
			DataRange dr;
			if (!m_dp.GetDataRange(dr) || !dr.SetData(&vyMI, &vxMI))
			{
				error_report("OnDelPart::fail in update data of anchor range ");
			}
		}

		///Sandy 2008-10-21 For indicate all anchors are deleted.
		if(vxMI.GetSize() == 0)
			post_getn_dialog_message(WM_USER_ON_GRAPH_OBJECT_CHANGE, WPARAM_NONE_ANCHOR);
		else
			post_getn_dialog_message(WM_USER_ON_GRAPH_OBJECT_CHANGE, nMkIndex);//Sandy 2008-4-21 should return anchor id
		return true;		

	}
	
	bool OnUpdate(int nMkIndex, MarkerInfo& mi)
	{
		return true;	
	}
	
	/// RVD 1/23/2009 QA80-13011 PA_MARKER_ACTIVATION
	//virtual	
	int ProcessEvents(const EventInfo& ei, MarkerInfo& mi)
	{
		switch( ei.GetEvent() )
		{
		///Jasmine 02/19/09 QA80-13131 PRESS_ENTER_TO_CLOSE_GRAPHDONEDLG
		case OE_KEYUP:
			
			if(VK_RETURN != ei.wParam.nVal)
				break;
			
			ASSERT( ei.GetSenderId() == mi.GetID() );
			
			TreeNode trUserInfo = ei.GetUserData();
			if( NULL != trUserInfo && trUserInfo.IsValid() )
		    {
		    	TreeNode trCore = trUserInfo.GetNode(PA_CORE_POINTER_TAGNAME);
		    	if(trCore)
		    	{
		    		DWORD 		dw 		= trCore.nVal;
		    		PAWizCore * paCore 	= NULL;

					try
					{
						paCore = (PAWizCore*)dw;
					}
					catch ( int nErr )
					{
						ASSERT(false);
						return false;
					}
					
					if(paCore)
					{
						ASSERT(paCore->m_dwGetDoneDlg);
						FUNC_CLOSE_GRAPH_DONE_WND pfn = Project.FindFunction("CloseGetDoneDlg", "Originlab\\GetPtsDlg", TRUE);
						if( !pfn || !pfn(paCore->m_dwGetDoneDlg) )
							ASSERT(FALSE);
					}
		    	}
		    }
			
			return 0;
			
			break;
		///End PRESS_ENTER_TO_CLOSE_GRAPHDONEDLG
		
		case OE_SELECT_MARKER_HANDLE:
		//if( OE_SELECT_MARKER_HANDLE == ei.GetEvent() ){
			OriginObject oo;
			mi.GetParent(oo);
			Selection.SelectAnchorSetHandle(oo, mi.GetID(), 1);		// activate 1st marker
			return 0;
			
			break;
			
		default:
			break;
		}
		
		return CurveMarkers::ProcessEvents(ei, mi);
	}
	/// end PA_MARKER_ACTIVATION
	
private:
	void sortAnchorsByXAscending(vector& vxMI, vector& vyMI)
	{
	    vector<uint> vnIndex;
	    vxMI.Sort(SORT_ASCENDING, TRUE, vnIndex);
	    vyMI.Reorder(vnIndex);
	}

};


int pa_anchors(const EventInfo& ei, const MarkerInfo& mk)
{
	ModifyBaselineMarkers mks(mk);
	return mks.ProcessEvents(ei, mk);
	
}

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

}

int pa_anchors_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 pa_anchors_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 pa_anchors_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
