/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/********************************************************************/
/**
 * @file CircleAroundCurve.cpp
 * @brief MGCircleAroundCurveTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/Ellipse.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "GLInputRealDlg.h"
#include "Common/CommandStateOwner.h"
#include "CurveCmd/CircleAroundCurve.h"


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

// MGCircleAroundCurveTool

MGCircleAroundCurveTool::MGCircleAroundCurveTool(MGCommandStateOwner* owner)
: MGLocateState(owner, UNLOCK_SNAP_ATTRIB, LINE_RUBBER, POINT_IPDRAW){
	turn_on_end();
	turn_on_near();
}

void MGCircleAroundCurveTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	// 円リアルタイムプレビュー
	std::unique_ptr<MGEllipse> spElps(create_circle(cursor()));

	// 描画
	if(spElps.get()){
		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		spElps->drawWire(sgl);
	}
}

MGEllipse* MGCircleAroundCurveTool::create_circle(const MGPosition& refpos)const{
	const LInfoVec& linfos=locates();
	if(linfos.empty()){
		return 0;
	}

	const MGPosition& center = linfos[0]->point_world();
	const double radius = center.distance(refpos);
	return new MGEllipse(center, radius, m_normal);
}

bool MGCircleAroundCurveTool::OnLocated(const MGLocateInfo& info){
	const LInfoVec& linfos=locates();
	switch(linfos.size()){
	case 0:
		break;
	case 1:
		{
			m_curve = dynamic_cast<const MGCurve*>(info.object());
			if(m_curve){
				// 法線方向を覚えておく。
				m_t=info.curve_parameter();
				m_normal = m_curve->direction(m_t);
			}else{
				cancel_last_locate();
			}
		}
		break;
	case 2:
		// 計算開始
		{
		std::unique_ptr<MGEllipse> circle(create_circle(linfos.back()->point_world()));
		UINT nIDS=IDS_FAIL_GENERATE_CURVE;
		if(circle.get()){
			nIDS=1;//successfully generated.
			add_object_to_current_group(circle.release());
		}
		return OnCommandEnd(nIDS);
		}
	default:
		break;
	}
	return false;
}

void MGCircleAroundCurveTool::prompt_message()const{
	const LInfoVec& linfos=locates();
	switch(linfos.size()){
	case 0:
		// 既存の曲線上点を選択する
		SetStatusMessage(IDS_PROMPT_POINT_ON_CURVE);
		break;
	case 1:
		// 半径を指定
		SetStatusMessage(IDS_PROMPT_ARC_TTR_2);
		break;
	}
}

bool MGCircleAroundCurveTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	const LInfoVec& linfos=locates();
	size_t np = linfos.size();

	switch(nChar){
	case 'r':
	case 'R':
		if(np==1){
			MGVector T,N,B;
			double curvature, torsion;
			m_curve->Frenet_frame(m_t,T,N,B,curvature,torsion);
			double radius;
			if(MGAZero(curvature))
				radius=10.;//10.????
			else
				radius=1./curvature;

			// 半径と向き入力待ちの状態、数値入力ダイアログ出現
			CString title;title.LoadString(IDS_PROMPT_CIRCLE_RADIUS);
			CGLInputRealDlg dlg(title);
			dlg.SetValue(radius);
			if(dlg.DoModal()==IDOK){
				double radius2 = dlg.GetValue();
				if(radius2>MGTolerance::wc_zero()){
					const MGPosition& center=linfos[0]->point_world();
					add_object_to_current_group(new MGEllipse(center, radius2, m_normal));
					return OnCommandEnd(1);
				}
			}
			pView->SetFocus();
		}
		break;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}
