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

/**
 * @file CPlaneRotate.cpp
 * @brief CPlaneRotate.h の実装
 */
#include "stdafx.h"
#include "mg/Ellipse.h"
#include "mg/CSisects.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "Misc/UserPrefValue.h"
#include "GLInputRealDlg.h"
#include "ViewCmd/CPlaneUtil.h"
#include "ViewCmd/CPlaneRotate.h"

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

// MGCPlaneRotateTool

#define RADIUS 10.
#define AXIS_LENGTH .1
MGCPlaneRotateTool::MGCPlaneRotateTool(fugenDoc* pDoc)
: MGLocateState(pDoc, ID_CPLANE_ROTATION),
m_rotation_axis(2),m_pViewTarget(pDoc->get_main_view()),
m_cplane(pDoc->get_main_view()->cplane()){
	m_xyzchar[0]='U';m_xyzchar[1]='V';m_xyzchar[2]='N';

	MGColor dummy;
	m_cplane.get_colors(dummy, m_colors[0], m_colors[1]);
	const MGContext& ctx=*(pDoc->context());
	const MGColor* gridColors=ctx.gridColors();
	m_colors[2]=gridColors[3];

	const MGPlane& pl = m_cplane.plane();
	m_axes[0]=pl.u_deriv();m_axes[1]=pl.v_deriv();m_axes[2]=pl.normal();	

	m_axisLenth[0]=m_cplane.uspan() * m_cplane.unum()*AXIS_LENGTH;
	m_axisLenth[1]=m_cplane.vspan() * m_cplane.vnum()*AXIS_LENGTH;
	m_axisLenth[2]=(m_axisLenth[0]+m_axisLenth[1])*.5;
}

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

void MGCPlaneRotateTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	if(locates().size()==0)
		return;

	sgl.LineWidth(2.f);
	int raxisP1=(m_rotation_axis+1)%3;
	const MGVector& Xaxis=m_axes[raxisP1];//CPlane's X axis.
	const MGVector& normal=m_axes[m_rotation_axis];//Rotation axis.
	double angle=getAngleUAxis(cursor(),m_origin,m_rotation_axis,m_axes); //angle of the rotation.

	//Arc from the X axis to the angle measuring line segment.
	double arcRadius=m_cplane.uspan()*RADIUS;
	if(angle>mgPAI)
		angle-=mgDBLPAI;
	MGEllipse arc(m_origin,m_origin+Xaxis*arcRadius, angle, normal);
	MGColor::get_instance(MGColor::White).exec(sgl);
	arc.drawWire(sgl);

	//Draw the orign axis to display rotation angle.
	MGPosition AngleP=m_origin+m_axes[raxisP1]*m_axisLenth[raxisP1];
	m_colors[raxisP1].exec(sgl);
	sgl.drawOpenPolyline(&m_origin,&AngleP,nullptr);

	// 線分で作業平面のプレビューを表現する。
	MGMatrix rotate(normal, angle);
	MGVector X=m_axes[0]*rotate, Y=m_axes[1]*rotate;
	PreviewCPlane(sgl,m_cplane,m_origin,X,Y,&m_colors[2]);
}

void MGCPlaneRotateTool::execRotate(double angle){
	const MGVector& normal=m_axes[m_rotation_axis];//Rotation axis.
	MGMatrix rotate(normal, angle);
	MGVector X=m_axes[0]*rotate, Y=m_axes[1]*rotate;
	ExecPlaneAction(m_pViewTarget, X,Y,m_origin);
}

bool MGCPlaneRotateTool::OnLocated(const MGLocateInfo& info){
	const LInfoVec& linfos=locates();
	switch(linfos.size()){
	case 1:
		m_origin=linfos[0]->point_world();
		break;
	case 2:
		execRotate(getAngleUAxis(linfos[1]->point_world(),
			m_origin,m_rotation_axis,m_axes));
		setActiveView(m_pViewTarget);
		return OnCommandEnd(1);// コマンド終了
	default:;
	}
	return false;
}

bool MGCPlaneRotateTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	static double angle=0.;
	switch(nChar){
	case 'k':
	case 'K':{
		// 角度入力の、数値入力ダイアログ出現
		double angleR;
		if(InputAngleFromDialogue(angle,pView,angleR)){
			execRotate(angleR);
			// コマンド終了
			setActiveView(m_pViewTarget);
			return OnCommandEnd(1);
		}

		}
		break;
	case 'u':
	case 'U': m_rotation_axis=0;// Rotate around x axis.
		break;
	case 'v':
	case 'V': m_rotation_axis=1;// Rotate around y axis.
		break;
	case 'n':
	case 'N': m_rotation_axis=2;// Rotate around z axis.
		break;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

void MGCPlaneRotateTool::prompt_message() const{
	const LInfoVec& linfos=locates();
	size_t np=linfos.size();
	if(np==1){
		int angleBase=(m_rotation_axis+1)%3;
		char baseC=m_xyzchar[angleBase];
		char axisC=m_xyzchar[m_rotation_axis];
		char nexBaseC=m_xyzchar[(angleBase+1)%3];
		SetStatusMessage(IDS_PROMPT_CPLANE_ROTATE_ANGLE,
			baseC,axisC,baseC,baseC,nexBaseC,nexBaseC);
	}else{
		SetStatusMessage(IDS_PROMPT_CPLANE_ORIGIN);
	}
}
