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

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

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

// MGArcCenStAngTool

MGArcCenStAngTool::MGArcCenStAngTool(MGCommandStateOwner* owner)
: MGLocateState(owner, UNLOCK_SNAP_ATTRIB, LINE_RUBBER, POINT_IPDRAW),
m_bOpposite(false){
}

MGArcCenStAngTool::MGArcCenStAngTool(fugenDoc* doc)
: MGLocateState(doc,ID_CURVE_CIRCLE_CENTER_RADIUS,LINE_RUBBER,POINT_IPDRAW),
m_bOpposite(false){
}

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

void MGArcCenStAngTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pSView){
	std::unique_ptr<MGCurve> arc(Compute(pSView, cursor()));
	if(!arc.get()){
		return;
	}

	const MGPosition& start = arc->start_point();
	const MGPosition& center = arc->center();
	const MGPosition& end = cursor();

	MGPosition rs = 2.*start - center;
	MGPosition re = center + (end-center).normalize()*start.distance(center)*2.;

	MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
	arc->drawWire(sgl);

	MGColor::get_instance(MGColor::White).exec(sgl);
	sgl.drawOpenPolyline(&rs,&(arc->center()),&re,nullptr);
}

bool MGArcCenStAngTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'r':
	case 'R':
		if(locates().size()<=1)//We accept only unti 1st point input.
			m_bOpposite = !m_bOpposite;
		break;
	default:;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGArcCenStAngTool::OnLocated(const MGLocateInfo& info){
	const LInfoVec& ipos=locates();
	size_t ninput=ipos.size();
	if(ninput<=2){
		if(ninput==2)
			setDrawerRubber(NO_RUBBER);
		else
			setDrawerRubber(LINE_RUBBER);
		return false;
	}

	// 計算開始
	MGCurve* arc = Compute(info.window(), ipos[2]->point_world());
	add_object_to_current_group(arc);
	return OnCommandEnd(1); // コマンド終了
}

MGCurve* MGArcCenStAngTool::Compute(fugenView* pView, const MGPosition& pos){
	LInfoVec& linfos=locates();
	size_t n=linfos.size();
	if(n < 2){
		return 0;
	}

	const MGPosition& center = linfos[0]->point_world();
	const MGPosition& start = linfos[1]->point_world();
	const MGPosition& end = pos;

	MGUnit_vector N(pView->cplane().plane().normal());
	if(m_bOpposite){
		N.negate();
	}

	double ang = MGCL::angle(center, start, end, N);
	return new MGEllipse(center, start, ang, N);
}

void MGArcCenStAngTool::prompt_message() const{
	const LInfoVec& linfos=locates();
	UINT nIDS = 0;
	CString clockwise;clockwise.LoadString(IDS_CLOCKWISE);
	CString unticlockwise;unticlockwise.LoadString(IDS_UNTICLOCKWISE);
	
	size_t ninput=linfos.size();
	switch(ninput){
	case 0:
		nIDS = IDS_PROMPT_ARC_CENTER;
		break;
	case 1:
		nIDS = IDS_PROMPT_ARC_START;
		break;
	case 2:
		nIDS = IDS_PROMPT_ARC_END;
		break;
	}
	if(ninput<=1){
		CString& dir1=m_bOpposite ? clockwise:unticlockwise;
		CString& dir2=m_bOpposite ? unticlockwise:clockwise;
		SetStatusMessage(nIDS,dir1,dir2);
	}else
		SetStatusMessage(nIDS);
}
