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

/**
 * @file PolygonEdge.cpp
 * @brief MGPolygonEdgeTool クラスのインプリメンテーション
 *
 * Vertical オプションの実装がまだ
 */
#include "stdafx.h"
#include "mg/Straight.h"
#include "Calc/line.h"
#include "Calc/mgcalc.h"
#include "fugenView.h"
#include "Misc/UserPreference.h"
#include "GLInputNumberDlg.h"
#include "Common/CommandStateOwner.h"
#include "CurveCmd/PolygonEdge.h"

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

namespace{
	const bool bFlip = false;
} // namespace

// MGPolygonEdgeTool

MGPolygonEdgeTool::MGPolygonEdgeTool(MGCommandStateOwner* owner)
: MGLocateState(owner, UNLOCK_SNAP_ATTRIB, NO_RUBBER, NO_IPDRAW),
m_nIDS(1), m_bVertical(false), // 垂直はオフからスタート
m_bFlip(bFlip){
}

MGPolygonEdgeTool::MGPolygonEdgeTool(fugenDoc* pDoc)
: MGLocateState(pDoc,ID_CURVE_POLYGON_EDGE,NO_RUBBER,NO_IPDRAW),
m_nIDS(1), m_bVertical(false), // 垂直はオフからスタート
m_bFlip(bFlip){
}

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

bool MGPolygonEdgeTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_N = pref.GetIntValue(upv_Curve_PolygonEdge_Num);
	m_bFlip = pref.GetBoolValue(upv_Curve_PolygonEdge_Flip);
	return false;
}

bool MGPolygonEdgeTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetIntValue(upv_Curve_PolygonEdge_Num, m_N);
	pref.SetBoolValue(upv_Curve_PolygonEdge_Flip, m_bFlip);

	return MGLocateState::terminate_tool(cancel);
}

bool MGPolygonEdgeTool::calculate(){
	const LInfoVec& linfos=locates();
	if(linfos.size() < 2){
		// cancel
		return false;
	}

	SetStatusMessage(IDS_PROMPT_COMPUTE);
	CWaitCursor hourglass;
	
	// 法線方向をセット
	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1=linfos[1]->point_world();
	MGVector normal = get_main_view()->cplane().plane().normal();
	if(m_bVertical && P1!=P0) {
		normal = normal * (P1-P0);
	}

	// 1. 多角形決定
	m_polygon=mgcalc::create_polygon_edge(
		MGStraight(P0, P1), (m_bFlip) ? -normal : normal, m_N);
	if(!m_polygon.get()){
		// failed
		m_nIDS = IDS_FAIL_GENERATE_CURVE;
		return false;
	}

	// 2. ドキュメント変更
	add_object_to_current_group(m_polygon.release());	
	return true;
}

void MGPolygonEdgeTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	const LInfoVec& linfos=locates();
	if(linfos.empty()){
		m_polygon.reset();
		return;
	}
	
	// 法線方向をセット
	MGVector normal = pView->cplane().plane().normal();
	const MGPosition& P0=linfos[0]->point_world();
	if(m_bVertical && cursor() != P0) {
		normal = normal * (cursor() - P0);
	}

	m_polygon=mgcalc::create_polygon_edge(
		MGStraight(P0, cursor()),(m_bFlip) ? -normal : normal,m_N);

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

bool MGPolygonEdgeTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'f':
	case 'F':
		m_bFlip = !m_bFlip;
		break;
	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 'v':
	case 'V':
	{
		m_bVertical = !m_bVertical;
		break;
	}
	default:;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

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

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

	if(!calculate()){
		return OnCommandEnd(m_nIDS);
	}
	return OnCommandEnd(1);
}

void MGPolygonEdgeTool::prompt_message()const{
	const LInfoVec& linfos=locates();
	CString strFlipYesNo;
	strFlipYesNo.LoadString(m_bFlip ? IDS_YES : IDS_NO);
	
	CString strVertYesNo;
	strVertYesNo.LoadString(m_bVertical ? IDS_YES : IDS_NO);

	switch(linfos.size()){
	case 0:
		SetStatusMessage(IDS_PROMPT_POLYGON_START, m_N, strVertYesNo);
		break;
	case 1:
		SetStatusMessage(IDS_PROMPT_POLYGON_END, m_N, strVertYesNo, strFlipYesNo);
		break;
	}
}
