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

/**
 * @file ExtendArcToPnt.cpp
 * @brief MGExtendArcToPnt クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/CompositeCurve.h"
#include "Calc/curve.h"
#include "Calc/mgcalc.h"
#include "fugenView.h"
#include "CurveCmd/ExtendArcToPnt.h"


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

// MGExtendArcToPnt

MGExtendArcToPnt::MGExtendArcToPnt(fugenDoc* pDoc)
: MGLocateState(pDoc,ID_CURVE_EXTEND_ARC_POINT,NO_RUBBER,NO_IPDRAW), m_nIDS(1){
	//曲線スナップをオン
	turn_on_near();
	turn_on_center();
	turn_on_knot();
	turn_on_end();
}

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

bool MGExtendArcToPnt::initiate_tool(){
	MGLocateState::initiate_tool();
	clear_pick_object();
	return false;
}

std::unique_ptr<MGEllipse> MGExtendArcToPnt::make_ellipse(
	const MGPosition& to_point
){
	MGLocateInfo& info=*(locates()[0]);
	const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
	double t=info.curve_parameter();
	double param = curve->param_se(t);
	MGVector T, N, B;
	double curva, torsion;
	curve->Frenet_frame(param, T, N, B, curva, torsion);

	std::unique_ptr<MGEllipse> arc(
		new MGEllipse(*curve, to_point, B, param));
	return arc;
}

bool MGExtendArcToPnt::calculate(){
	const LInfoVec& linfos=locates();
	assert(linfos.size()>=2);
	std::unique_ptr<MGEllipse> arc=make_ellipse(linfos[1]->point_world());
	if(!arc.get()){
		// failed
		return false;
	}

	// combine.
	const MGCurve* curve = dynamic_cast<const MGCurve*>(linfos[0]->object());
	MGCompositeCurve* compo=new MGCompositeCurve(arc.release());
	compo->connect_to_start(curve->clone());

	// やむをえない const_cast
	replace_object(const_cast<MGCurve*>(curve), compo);
	return true;
}

void MGExtendArcToPnt::do_make_temporary_display(mgSysGL& sgl,fugenView* pSView){
	std::unique_ptr<MGEllipse> ellipse;
	if(locates().size()>=1){
		ellipse = make_ellipse(cursor());
		if(ellipse.get()){
			MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
			ellipse->drawWire(sgl);
		}
	}
}

bool MGExtendArcToPnt::OnLocated(const MGLocateInfo& info){
	const LInfoVec& linfos=locates();
	switch(linfos.size()){
	case 0:
		break;
	case 1:
		{
			const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
			if(!curve){
				cancel_last_locate();
				return false;
			}
		}
		break;
	case 2:
		// 延長点が入力された
		if(!calculate()){
			// failed
			return OnCommandEnd(m_nIDS);
		}
		return OnCommandEnd(1);
	}
	return false;
}

void MGExtendArcToPnt::prompt_message() const{
	if(locates().empty()){
		SetStatusMessage(IDS_PROMPT_CURVE_END);
	}else{
		SetStatusMessage(IDS_PROMPT_DESTINATION);
	}
}

