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

/**
 * @file PolygonStar.cpp
 * @brief MGPolygonStarTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "Calc/line.h"
#include "Calc/mgcalc.h"
#include "fugenView.h"
#include "GLInputNumberDlg.h"
#include "Common/CommandStateOwner.h"
#include "Misc/UserPreference.h"
#include "CurveCmd/PolygonStar.h"

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

// MGPolygonStarTool

MGPolygonStarTool::MGPolygonStarTool(MGCommandStateOwner* owner)
:MGLocateState(owner,UNLOCK_SNAP_ATTRIB,NO_RUBBER,POINT_IPDRAW),
m_bVertical(false) // 垂直はオフからスタート
{
}

MGPolygonStarTool::MGPolygonStarTool(fugenDoc* pDoc)
:MGLocateState(pDoc,ID_CURVE_POLYGON_STAR,NO_RUBBER,POINT_IPDRAW),
m_bVertical(false) // 垂直はオフからスタート
{
}

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

bool MGPolygonStarTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_VertexNum = pref.GetIntValue(upv_Curve_PolygonStar_Num);
	return false;
}

bool MGPolygonStarTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetIntValue(upv_Curve_PolygonStar_Num, m_VertexNum);

	return MGLocateState::terminate_tool(cancel);
}

void MGPolygonStarTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	const LInfoVec& linfos=locates();
	size_t np = linfos.size();
	if(!np){
		return;
	}

	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1 = np>=2 ? linfos[1]->point_world() : cursor();

	// 法線方向をセット
	MGVector normal=m_normal;
	if(m_bVertical){
		normal = m_normal*(P1-P0);
	}
	std::unique_ptr<MGCurve> star;
	switch(linfos.size()){
	case 1:
		// 通常の多角形を描くようにオブジェクトを生成
		star=mgcalc::create_polygon_ins(P0,normal,m_VertexNum,cursor());
		break;
	case 2:
		double radius2nd = cursor().distance(P0);
		// 星型を描くようにオブジェクトを生成
		star=mgcalc::create_polygon_star(P0,normal,m_VertexNum,P1,radius2nd);
		break;
	}

	if(star.get()){
		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		star->drawWire(sgl);
	}
}

bool MGPolygonStarTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'n':
	case 'N':
		{
		// 辺の数をダイアログ入力で変更する
			CString strCaption; VERIFY(strCaption.LoadString(IDS_CAPTION_VERT_NUM));
			CGLInputNumberDlg dlg(CString(), strCaption);
			dlg.SetValue(m_VertexNum);
			if(IDOK == dlg.DoModal()){
				int n = dlg.GetValue();
				if(n >= 2)
					m_VertexNum = n;
			}
			pView->SetFocus();
		}
		break;
	case 'v':
	case 'V':
		// 「CPlane に対して垂直な多角形」モードオン(一方通行)
		if(locates().size() <= 1){
			m_bVertical = !m_bVertical;
		}
		break;
	default:
		;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGPolygonStarTool::OnLocated(const MGLocateInfo& info){
	LInfoVec& linfos=locates();
	size_t np = linfos.size();
	if(np>=1){	
		const MGPosition& P0=linfos[0]->point_world();
		switch(np){
		case 1:
			//Save the normal of the current cplane.
			m_normal=linfos[0]->window()->cplane().plane().normal();
			break;

		case 2:
			break;

		case 3:
			{
			const MGPosition& P2=linfos[2]->point_world();
			if(P0 == P2)
				cancel_last_locate();
			}
			break;

		}
	}

	// 再描画
	if(linfos.size()<3){
		return false;
	}

	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1=linfos[1]->point_world();
	const MGPosition& P2=linfos[2]->point_world();

	// 法線方向をセット
	MGVector normal=m_normal;
	if(m_bVertical) {
		normal = normal*(P1-P0);
	}

	// 1. 多角形決定
	double radius2nd = P2.distance(P0);
	std::unique_ptr<MGCurve> star=
		mgcalc::create_polygon_star(P0,normal,m_VertexNum,P1,radius2nd);
	if(!star.get()){
		// failed
		return OnCommandEnd(IDS_FAIL_GENERATE_CURVE);
	}

	// 2. ドキュメント変更
	add_object_to_current_group(star.release());	
	return OnCommandEnd(1);
}

void MGPolygonStarTool::prompt_message() const{
	CString strVertYesNo;
	strVertYesNo.LoadString(m_bVertical ? IDS_YES : IDS_NO);

	int nIDS = 0;
	switch(locates().size()){
	case 0:
	{
		nIDS = m_bVertical ? IDS_PROMPT_STAR_CENTER_VERTICAL : IDS_PROMPT_STAR_CENTER;
		SetStatusMessage(nIDS, m_VertexNum, strVertYesNo);
		break;
	}
	case 1:
		nIDS = IDS_PROMPT_STAR_CORNER;
		SetStatusMessage(nIDS, m_VertexNum, strVertYesNo);
		break;
	case 2:
		nIDS = IDS_PROMPT_STAR_RADIUS;
		SetStatusMessage(nIDS, m_VertexNum);
		break;
	}
	ASSERT(nIDS);
}
