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

/**
 * @file ElpsAroundCurve.cpp
 * @brief MGElpsAroundCurveTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/Ellipse.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "Common/CommandStateOwner.h"
#include "CurveCmd/ElpsAroundCurve.h"


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

// MGElpsAroundCurveTool

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

bool MGElpsAroundCurveTool::calculate(){
	std::unique_ptr<MGEllipse> spElps(create_ellipse(locates().back()->point_world()));
	if(spElps.get()){
		add_object_to_current_group(spElps.release());
		return true;
	}else{
		return false;
	}
}

void MGElpsAroundCurveTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	if(locates().size() < 2)
		return;

	// 楕円リアルタイムプレビュー
	std::unique_ptr<MGEllipse> spElps(create_ellipse(cursor()));

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

		MGColor::get_instance(MGColor::White).exec(sgl);
		MGVector apex = spElps->eval(mgHALFPAI);
		sgl.Begin(GL_LINES);
		sgl.Vertex3dv(spElps->center().data());
		sgl.Vertex3dv(apex.data());
		sgl.End();

		MGColor::get_instance(MGColor::Black).exec(sgl);
		sgl.drawPoint(apex[0], apex[1], apex[2]);
	}
}

MGEllipse* MGElpsAroundCurveTool::create_ellipse(const MGPosition& epos)const{
	const LInfoVec& linfos=locates();
	size_t np = linfos.size();
	if(np<2){
		return 0;
	}

	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1=linfos[1]->point_world();
	const MGPosition& center = P0;
	const MGVector axis1 = P1 - center;

	MGVector axis2 = m_normal * axis1;
	double mag = epos.distance(center);
	axis2 *= mag / axis2.len();
	return new MGEllipse(center, axis1, axis2, MGInterval(0., mgDBLPAI));
}

bool MGElpsAroundCurveTool::OnKeyDown(
	fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags
){
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGElpsAroundCurveTool::OnLocated(const MGLocateInfo& info){
	switch(locates().size()){
	case 1:{
			const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
			if(curve){
				// 法線方向を覚えておく。
				m_normal = curve->direction(info.curve_parameter());
			}else{
				cancel_last_locate();
			}
		}
		break;
	case 3:
		// 計算開始
		if(!calculate()){
			// failed
			return OnCommandEnd(2);
		}
		return OnCommandEnd(1);
	default:;
	}
	return false;
}

void MGElpsAroundCurveTool::prompt_message() const{
	switch(locates().size()){
	case 0:
		// 既存の曲線上点を選択する
		SetStatusMessage(IDS_PROMPT_POINT_ON_CURVE);
		break;
	case 1:
		// 軸 1 の端点をロケート
		SetStatusMessage(IDS_PROMPT_ELLIPSE_AXIS_NTH, 1);
		break;
	case 2:
		// 軸 2 の端点をロケート
		SetStatusMessage(IDS_PROMPT_ELLIPSE_AXIS_NTH, 2);
		break;
	}
}
