#include "stdafx.h"

#include "fugenDoc.h"
#include "mg/Ellipse.h"
#include "mg/Plane.h"
#include "Calc/line.h"
#include "fugenView.h"
#include "Common/CommandStateOwner.h"
#include "GLInputNumberDlg.h"
#include "PolygonAroundCurveTool.h"

namespace{
	const int  N     = 5;
}

MGPolygonAroundCurveTool::MGPolygonAroundCurveTool(MGCommandStateOwner* owner)
: MGLocateState(owner, UNLOCK_SNAP_ATTRIB, LINE_RUBBER, POINT_IPDRAW), m_N(N){
	turn_on_near();
}

bool MGPolygonAroundCurveTool::calculate(){
	std::unique_ptr<MGCurve> polygon_curve(create_polygon(locates().back()->point_world()));
	if(polygon_curve.get()){
		add_object_to_current_group(polygon_curve.release());
		return true;
	}else{
		return false;
	}
}

void MGPolygonAroundCurveTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	if(locates().empty()){
		return;
	}

	// 円リアルタイムプレビュー
	std::unique_ptr<MGCurve> polygon_curve(create_polygon(cursor()));

	// 描画
	if(polygon_curve.get()){
		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		polygon_curve->drawWire(sgl);
	}
}

MGCurve* MGPolygonAroundCurveTool::create_polygon(const MGPosition& refpos) const{
	const LInfoVec& linfos=locates();
	if(linfos.empty()){
		return 0;
	}

	const MGPosition& center = linfos[0]->point_world();
	MGPlane plane(m_normal, center);
	MGPosition vertex_uv = plane.uv(refpos - center);
	MGPosition vertex_xy = center+(plane.u_deriv()*vertex_uv(0)+plane.v_deriv()*vertex_uv(1));
	return mgcalc::create_polygon_ins(center, m_normal, m_N, vertex_xy).release();
}

bool MGPolygonAroundCurveTool::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_N);
			if(IDOK == dlg.DoModal()){
				int n = dlg.GetValue();
				if(n >= 2){
					m_N = n;
				}
			}
			pView->SetFocus();
		}
		break;
	default:;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGPolygonAroundCurveTool::OnLocated(const MGLocateInfo& info){
	switch(locates().size()){
	case 0:
		break;
	case 1:
		{
			const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
			if(curve){
				// 法線方向を覚えておく。
				m_normal = curve->direction(info.curve_parameter());
			}else{
				cancel_last_locate();
			}
		}
		break;
	case 2:
		// 計算開始
		if(!calculate()){
			// failed
			return OnCommandEnd(2);
		}
		return OnCommandEnd(1);
	default:
		break;
	}
	return false;
}

void MGPolygonAroundCurveTool::prompt_message() const{
	switch(locates().size()){
	case 0:
		// 既存の曲線上点を選択する
		SetStatusMessage(IDS_PROMPT_POLYGON_POINT_ON_CURVE, m_N);
		break;
	case 1:
		// 半径を指定
		SetStatusMessage(IDS_PROMPT_POLYGON_VERT_RADIUS, m_N);
		break;
	}
}
