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

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

// MGPointClosestTool

MGPointClosestTool::MGPointClosestTool(fugenDoc* pDoc)
: MGCommandStateOwner(pDoc, ID_CURVE_CLOSEST){
}

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

bool MGPointClosestTool::initiate_tool(){
	MGCommandStateOwner::initiate_tool();
	if(current_object_is_valid(mgAll_Curve,m_curve)){
		set_current_object(m_curve);
		//Input a point.
		set_child_current_command(new MGPointClosestToolIPoint(this));
	}else{
		//select a curve to evaluate.
		set_child_current_command(new MGPointClosestToolSCurve(this));
	}
	return false;
}

bool MGPointClosestTool::make_model(){
	const MGPosition& pos = locates().front()->point_world();
	MGPickObjects::iterator first = m_curve.begin(), last = m_curve.end();
	MGGelPositions gelps;

	for(; first != last; ++first){
		MGPickObject& pobj=**first;
		MGCurve& curve=*dynamic_cast<MGCurve*>(pobj.top_object());
		double param = curve.closest(pos);
		MGPoint* point = new MGPoint(curve.eval(param));
		gelps.push_back(MGGelPosition(pobj.bottom_group(),point));
	}

	if(gelps.empty()){
		// failed
		return false;
	}
	
	add_object_to_document(gelps);
	return true;
}

///////////////Closest curve selection class/////////////

MGPointClosestToolSCurve::MGPointClosestToolSCurve(MGPointClosestTool* owner)
	 : MGSelectState(
		 owner,
		 MGSelectState::MULTIPLE_SELECT,  // 複数選択可
		 mgAll_Curve
		 )
{
}

bool MGPointClosestToolSCurve::initiate_tool(){
	MGSelectState::initiate_tool();
	set_add_mode();
	SetStatusMessage(IDS_PROMPT_CURVE);
	return false;
}

bool MGPointClosestToolSCurve::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case VK_RETURN:
		// 曲線決定
		{
			MGPointClosestTool* owner = state_owner();
			owner->m_curve = current_objects();
			set_sibling_next_command(new MGPointClosestToolIPoint(owner));
		}
		return false;
	default:
		return MGSelectState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
	}
}

/////////////Point input class//////////////
MGPointClosestToolIPoint::MGPointClosestToolIPoint(MGPointClosestTool* owner)
: MGLocateState(owner, UNLOCK_SNAP_ATTRIB, NO_RUBBER, POINT_IPDRAW){
}

bool MGPointClosestToolIPoint::initiate_tool(){
	MGLocateState::initiate_tool();
	SetStatusMessage(IDS_PROMPT_POSITION);
	return false;
}

bool MGPointClosestToolIPoint::OnLocated(
	const MGLocateInfo& linfo
){
	MGPointClosestTool* owner=state_owner();

	if(!owner->make_model()){
		// failed
		return owner->OnCommandEnd(2);
	}
	return owner->OnCommandEnd(1);
}
