/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/

/**
 * @file CPlaneCurve.cpp
 * @brief CPlaneCurve.h の実装
 */
#include "stdafx.h"
#include "fugen.h"
#include "fugenView.h"
#include "ViewCmd/CPlaneUtil.h"
#include "ViewCmd/CPlaneToObj.h"

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

// MGCPlaneCurveIPoint

MGCPlaneCurveIPoint::MGCPlaneCurveIPoint(
	MGCommandStateOwner* owner,
	fugenView* pView, // 対象となるビュー
	const MGCurve* curve // CPlane をフィットさせる曲線
): MGLocateOnObjects(curve,owner),
m_pView(pView),m_curve(curve), m_CplaneKind(2),m_OnlyMove(false){
	const MGContext& ctx=*(document()->context());
	const MGColor* gridColors=ctx.gridColors();
	m_zColor=&gridColors[3];

	if(!m_pView->is_mainView())
		m_OnlyMove=true;
	turn_on_near();
	turn_on_end();
	turn_on_center();
}

// CPlaneの(X, Y)軸は曲線のFrenet frame（T,N,B)のいずれかとなるよう決定
void MGCPlaneCurveIPoint::compute_plane(MGPosition& org,MGVector& X,MGVector& Y){
	org = m_curve->eval(m_param);
	const MGPlane& pl=m_pView->cplane().plane();
	if(m_OnlyMove){
		X=pl.u_deriv();
		Y=pl.v_deriv();
	}else{
		MGVector Normal[3];
		MGVector& T=Normal[0];
		MGVector& N=Normal[1];
		MGVector& B=Normal[2];
		double curva, torsion;
		m_curve->Frenet_frame(m_param, T, N, B, curva, torsion);
		if(MGAZero(curva)){
			MGVector B2=pl.normal();
			B=B2.orthogonize(T);
			N=B*T;
		}
		X=Normal[(m_CplaneKind+1)%3];
		Y=Normal[(m_CplaneKind+2)%3];
	}
}

void MGCPlaneCurveIPoint::display(mgSysGL& sgl,fugenView* pView){
	MGVector X,Y;
	MGPosition org;
	// CPlaneの(X, Y)軸は曲線のFrenet frame（T,N,B)のいずれかとなるよう決定
	compute_plane(org,X,Y);
	const MGConstructionPlane& cplane = m_pView->cplane();
	PreviewCPlane(sgl,cplane, org,X,Y,m_zColor);
}

bool MGCPlaneCurveIPoint::OnKeyDown(
	fugenView* pView,///<The fugenView pointer where this event took place.
	UINT nChar,	UINT nRepCnt, UINT nFlags
		///<These parameters are of CWnd::OnKeyDown. See the document.
){
	if(m_pView->is_mainView()){
		switch(nChar){
		case 'm':
		case 'M':
			m_OnlyMove=!m_OnlyMove;
		case 't':
		case 'T':
			m_CplaneKind=0;
			break;
		case 'n':
		case 'N':
			m_CplaneKind=1;
			break;
		case 'b':
		case 'B':
			m_CplaneKind=2;
			break;
		}
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGCPlaneCurveIPoint::OnLocated(const MGLocateInfo& info){	
	// 曲線上のパラメータが取れているはず...
	const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
	if(curve != m_curve){
		return false;
	}
	m_param = info.curve_parameter();

	// OK. CPlaneの計算を開始する
	MGVector X,Y;
	MGPosition org;
	compute_plane(org,X,Y);
	ExecPlaneAction(m_pView, X, Y, org);
	return OnCommandEnd(1);
}

void MGCPlaneCurveIPoint::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	const MGCurve* curve = snappedCurve();
	if(m_curve == curve){
		m_param = snappedCurveParam();
		display(sgl,pView);
	}
}

void MGCPlaneCurveIPoint::prompt_message() const{
	static const std::string current[3]={"T","N","B"};
	static const std::string KB[3]={"[N-norml]","[B-binorml]","[T-tangnt]"};

	CString moveOnly;moveOnly.LoadString(IDS_STRING_MOVE_ONLY);
	CString rotateToo;rotateToo.LoadString(IDS_STRING_ROTATE_TOO);

	CString Nkind(current[m_CplaneKind].c_str());
	CString KBkind1(KB[m_CplaneKind].c_str());
	CString KBkind2(KB[(m_CplaneKind+1)%3].c_str());

	if(m_OnlyMove)
		SetStatusMessage(IDS_PROMPT_CPLCRV_ORIGIN2,moveOnly,rotateToo);
	else{
		SetStatusMessage(IDS_PROMPT_CPLCRV_ORIGIN,
			rotateToo,moveOnly,Nkind,KBkind1,KBkind2);
	}
}
