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

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

// MGCornerR_CCRTool

MGCornerR_CCRTool::MGCornerR_CCRTool(fugenDoc* pDoc)
: MGLocateState(pDoc,ID_CURVE_ARC_TTR,NO_RUBBER,POINT_IPDRAW){
	turn_on_near();
	turn_on_end();
}

MGCornerR_CCRTool::MGCornerR_CCRTool(MGCommandStateOwner* owner)
: MGLocateState(owner, UNLOCK_SNAP_ATTRIB, NO_RUBBER, POINT_IPDRAW){
	turn_on_near();
	turn_on_end();
}

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

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

bool MGCornerR_CCRTool::input_param(
	const MGPosition& p1,	//sample point 1.
	const MGPosition& p2,	//sample point 2.
	double& radius			//radius will be output.
){
	SetStatusMessage(IDS_PROMPT_CIRCLE_RADIUS);
	CString str;
	VERIFY(str.LoadString(IDS_CAPTION_CORNER_R));

	CGLInputRealDlg dlg(CString(), str);
	dlg.SetValue((p1-p2).len()*.5);
	bool bOK = (IDOK == dlg.DoModal());
	radius=dlg.GetValue();
	return bOK;
}

bool MGCornerR_CCRTool::OnCommandEnd(
	UINT nIDS,	//=0: erase the current message, and display no messages.
				//=1: display "xxxx" normally end.
				//otherwise: nIDS is a string id, and load the message from string table to display.
	bool erase_temporary_display
){
	const LInfoVec& linfos=locates();
	if(linfos.size()<2)
		return MGLocateState::OnCommandEnd(3);

	const MGCurve& c1=*(dynamic_cast<const MGCurve*>(linfos[0]->object()));
	double t1=linfos[0]->curve_parameter();
	const MGCurve& c2=*(dynamic_cast<const MGCurve*>(linfos[1]->object()));
	double t2=linfos[1]->curve_parameter();
	MGPosition p1 = c1.eval(t1);
	MGPosition p2 = c2.eval(t2);

	double radius;
	if(!input_param(p1,p2,radius)){
		// cancel
		return MGLocateState::OnCommandEnd(3);
	}

	// 計算開始
	MGPosition closestParam12 = c1.closest(c2);
	MGPosition p0=(c1.eval(closestParam12[0])+c2.eval(closestParam12[1]))/2.;
	MGUnit_vector normal = (p1 - p0) * (p2 - p0);
	int ret = 0;
	std::unique_ptr<MGEllipse> arc(
		new MGEllipse(c1,c2,normal,radius,t1,t2,ret)
	);
	if(ret){
		// failed
		return MGLocateState::OnCommandEnd(IDS_FAIL_GENERATE_CURVE);
	}
	add_object_to_current_group(arc.release());
	return MGLocateState::OnCommandEnd(nIDS);
}

bool MGCornerR_CCRTool::OnLocated(const MGLocateInfo& info){
	if(info.is_deleted()){
		return false;
	}

	const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
	if(!curve){
		// 曲線上の点以外のクリックは認めない
		cancel_last_locate();
		return false;
	}

	const LInfoVec& locs=locates();
	size_t np=locs.size();
	if(np<=1){
		return false;
	}

	if(locs[0]->object()==locs[1]->object()){
		// 前回の曲線と同じではいけない(MGCL)?
		cancel_last_locate();
		return false;
	}

	// 計算開始
	return OnCommandEnd(1);
}

void MGCornerR_CCRTool::prompt_message() const{
	size_t np=locates().size();
	SetStatusMessage(IDS_PROMPT_CIRCLE_BASELINE, np+1);
}
