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

/**
 * @file PolygonVertex.cpp:
 * @brief MGPolygonVertexTool クラスのインプリメンテーション
 *
 * Vertical オプションの実装がまだ
 */
#include "stdafx.h"
#include "Calc/line.h"
#include "Calc/mgcalc.h"
#include "Misc/UserPreference.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "CurveCmd/Polygon.h"
#include "CurveCmd/PolygonEdge.h"
#include "CurveCmd/PolygonStar.h"
#include "GLInputNumberDlg.h"
#include "PolygonAroundCurveTool.h"
#include "CurveCmd/PolygonVertex.h"

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

// MGPolygonVertexTool

MGPolygonVertexTool::MGPolygonVertexTool(MGCommandStateOwner* owner)
: MGLocateState(owner,UNLOCK_SNAP_ATTRIB,NO_RUBBER,POINT_IPDRAW),
m_bInscrib(true),  // 必ず内接モードからスタートする
m_bVertical(false) // 垂直はオフからスタート
{
}

bool MGPolygonVertexTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_N = pref.GetIntValue(upv_Curve_PolygonVertex_Num);
	return false;
}

bool MGPolygonVertexTool::terminate_tool(bool cancel){
	UserPreference& pref =UserPreference::getInstance();
	pref.SetIntValue(upv_Curve_PolygonVertex_Num, m_N);

	return MGLocateState::terminate_tool(cancel);
}

void MGPolygonVertexTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	LInfoVec& linfos=locates();
	std::unique_ptr<MGCurve> curve;
	if(!locates().empty()){
		const MGPosition& P0=linfos[0]->point_world();
		const MGPosition& P1=cursor();
		if(P0!=P1){
			MGVector normal=linfos[0]->window()->cplane().plane().normal();
			if(m_bVertical) {
				normal = normal*(P1-P0);
			}
			if(m_bInscrib){
				curve = mgcalc::create_polygon_ins(P0, normal, m_N, P1);
			}else{
				curve = mgcalc::create_polygon_cir(P0, normal, m_N, P1);
			}

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

bool MGPolygonVertexTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'a':
	case 'A':
		// around curve
		set_sibling_next_command(new MGPolygonAroundCurveTool(get_owner_command()));
		return false;
	case 'c':
	case 'C':
		if(m_bInscrib){
			// 一度だけチェンジ可能なオプション
			m_bInscrib = false;
		}
		break;
	case 'e':
	case 'E':
		// edge
		set_sibling_next_command(new MGPolygonEdgeTool(get_owner_command()));
		return false;
	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;
	case 's':
	case 'S':
		// star
		set_sibling_next_command(new MGPolygonStarTool(get_owner_command()));
		return false;
	case 'v':
	case 'V':
		// 「CPlane に対して垂直な多角形」モードオン(一方通行)
		if(locates().size() <= 1){
			m_bVertical = !m_bVertical;
		}
		break;
	default:
		;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGPolygonVertexTool::OnLocated(const MGLocateInfo& info){
	LInfoVec& linfos=locates();	

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

	// 法線方向をセット
	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1=linfos[1]->point_world();
	MGVector normal=linfos[0]->window()->cplane().plane().normal();
	if(m_bVertical) {
		normal = normal*(P1-P0);
	}
	
	// 1. 多角形決定
	std::unique_ptr<MGCurve> curve;
	if(m_bInscrib){
		curve=mgcalc::create_polygon_ins(P0,normal,m_N,P1);
	}else{
		curve=mgcalc::create_polygon_cir(P0,normal,m_N,P1);
	}

	if(!curve.get()){
		// failed
		return OnCommandEnd(IDS_FAIL_GENERATE_CURVE);
	}

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

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

	UINT ids=IDS_PROMPT_POLYGON_CORNER;
	size_t n=locates().size();
	if(n==0){
		if(m_bInscrib){
			ids=IDS_PROMPT_POLYGON_INS;
		}else{
			ids=IDS_PROMPT_POLYGON_CIR;
		}
	}
	SetStatusMessage(ids, m_N, strVertYesNo);
}
