/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/********************************************************************/
// EvalCSFold.cpp: MGEvalCSFoldTool クラスのインプリメンテーション

#include "stdafx.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "EvalCmd/EvalCSFold.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

// MGEvalCSFoldTool

MGEvalCSFoldTool::MGEvalCSFoldTool(fugenDoc* pDoc)
	 : MGCommandStateOwner(pDoc, ID_EVAL_CURVE_SURFACE_2){}

MGCommandBase* MGEvalCSFoldTool::initial_clone(fugenDoc* pDoc) const
{
	return new MGEvalCSFoldTool(pDoc);
}

bool MGEvalCSFoldTool::initiate_tool(){
	MGCommandStateOwner::initiate_tool();

	const MGPickObjects& cobj=current_objects();
	m_pocurve= cobj.select_1st_curve();
	m_posurf=cobj.select_1st_fsurface();

	if(!m_pocurve.is_null() && !m_posurf.is_null()){
		evaluate();
		return OnCommandEnd(1,false);
	}
	if(is_breaking_command())
		return true;//If breaking into the other command, terminate this command.

	set_current_object(m_pocurve);
	append_current_object(m_posurf);

	if(m_pocurve.is_null()){
		// 曲線選択
		set_child_current_command(new MGEvalCSFoldSCurve(this));
		return false;
	}

	if(m_posurf.is_null()){
		// 曲線選択
		set_child_current_command(new MGEvalCSFoldSSurf(this));
		return false;
	}

	return false;
}

void MGEvalCSFoldTool::displayInfoOnMessageBox(
	const MGFSurface& surf,
	const MGPosition& uv,
	const MGCurve& curve,
	double t
){	
	// 計算開始
	SetStatusMessage(IDS_PROMPT_COMPUTE);
	CWaitCursor sandglass;

	// 始点側
	MGPosition end = curve.eval(t);
	MGUnit_vector direction = curve.eval(t,1);
	MGPosition PonS=surf.eval(uv);
	double distance=PonS.distance(end);
	MGUnit_vector normal = surf.unit_normal(uv);
	MGUnit_vector tmp = direction * normal;//

	CString str;
	str.Format(IDS_FORMAT_EVAL_CSFOLD,
	   end[0], end[1], end[2],//曲線上の点
	   PonS[0], PonS[1], PonS[2],//曲面上の点
	   distance,
	   direction[0], direction[1], direction[2],
	   normal[0], normal[1], normal[2],
	   MGCL::radian_to_degree(direction.angle(normal)),
	   tmp[0], tmp[1], tmp[2]
	   );
	putInOutputWindow(str);
}

bool MGEvalCSFoldTool::evaluate(){
	const MGCurve& curve=*(dynamic_cast<const MGCurve*>(m_pocurve.top_object()));
	const MGFSurface& surf=*(dynamic_cast<const MGFSurface*>(m_posurf.top_object()));

	// 計算開始
	SetStatusMessage(IDS_PROMPT_COMPUTE);
	CWaitCursor sandglass;

	// 始点側
	double ts=curve.param_s();
	bool ts_is_on_the_surface;
	MGPosition uvs(2);
	MGPosition PCS=curve.eval(ts);
	if(ts_is_on_the_surface=surf.on(PCS,uvs)){
		displayInfoOnMessageBox(surf,uvs,curve,ts);
	}
	// 終点側
	double te=curve.param_e();
	bool te_is_on_the_surface;
	MGPosition uve(2);
	MGPosition PCE=curve.eval(te);
	if(te_is_on_the_surface=surf.on(PCE, uve)){
		displayInfoOnMessageBox(surf,uve,curve,te);
	}

	if(ts_is_on_the_surface || te_is_on_the_surface)
		return true;

	double dists=PCS.distance(surf.eval(uvs));
	double diste=PCE.distance(surf.eval(uve));
	if(dists>diste){
		ts=te; uvs=uve;
	}
	displayInfoOnMessageBox( surf,uvs,curve,ts);
	return true;
}

// MGEvalCSFoldSCurve

MGEvalCSFoldSCurve::MGEvalCSFoldSCurve(MGCommandStateOwner* owner)
: MGSelectState(owner, MGSelectState::SINGLE_SELECT, mgAll_Curve){}

bool MGEvalCSFoldSCurve::initiate_tool(){
	MGSelectState::initiate_tool();
	set_add_mode();
	prohibit_unselect();

	// 最初のメッセージ
	SetStatusMessage(IDS_PROMPT_CURVE);
	return false;
}

bool MGEvalCSFoldSCurve::OnSelected(
	fugenView* window,//The fugenView pointer where point input event took place.
	MGPickObjects&	objs,	//selected objects at this selection operation.
	MGPickObjects&	unselected_objects	//unselected objects at this selection operation.
		//unselected_objects.size()>=1 only when the already selected objects are selected
		//when add mode is set(or when operation is done with a crtl key pressed).
){
	MGEvalCSFoldTool* owner = state_owner();
	// 曲線をセット
	owner->m_pocurve = objs[0];

	if(owner->m_posurf.is_null()){
		// 曲面選択へ進む
		set_sibling_next_command(new MGEvalCSFoldSSurf(owner));
		return false;
	}

	// 計算開始
	owner->evaluate();
	return owner->OnCommandEnd(1,false);
}

// MGEvalCSFoldSSurf
MGEvalCSFoldSSurf::MGEvalCSFoldSSurf(MGCommandStateOwner* owner)
: MGSelectState(owner, MGSelectState::SINGLE_SELECT, mgAll_FSurface){	}

bool MGEvalCSFoldSSurf::initiate_tool(){
	MGSelectState::initiate_tool();
	set_add_mode();
	prohibit_unselect();

	// 最初のメッセージ
	SetStatusMessage(IDS_PROMPT_SURFACE);
	return false;
}

bool MGEvalCSFoldSSurf::OnSelected(
	fugenView* window,//The fugenView pointer where point input event took place.
	MGPickObjects&	objs,	//selected objects at this selection operation.
	MGPickObjects&	unselected_objects	//unselected objects at this selection operation.
		//unselected_objects.size()>=1 only when the already selected objects are selected
		//when add mode is set(or when operation is done with a crtl key pressed).
){
	MGEvalCSFoldTool* owner = state_owner();

	// 曲面をセット
	owner->m_posurf = objs[0];
	if(owner->m_pocurve.is_null()){
		// 曲面選択へ進む
		set_sibling_next_command(new MGEvalCSFoldSCurve(owner));
		return false;
	}

	// 計算開始
	owner->evaluate();
	return owner->OnCommandEnd(1,false);
}
