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

/**
 * @file RectVertical.cpp
 * @brief MGRectVerticalTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "mg/CSisects.h"
#include "mg/Straight.h"
#include "Calc/mgcalc.h"
#include "fugen.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "Misc/UserPreference.h"
#include "GLInputRealDlg.h"
#include "Common/CommandStateOwner.h"
#include "CurveCmd/RectVertical.h"

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

// MGRectVerticalTool

namespace{
	const double dRadius = 3.0;
	const double dRho    = 0.5;
	const bool   bCircle = true;
}

MGRectVerticalTool::MGRectVerticalTool(fugenDoc* pDoc)
:MGLocateState(pDoc,ID_CURVE_RECT_VERTICAL,LINE_RUBBER,POINT_IPDRAW),
m_dRadius(dRadius), m_bRound(false){
}

MGRectVerticalTool::MGRectVerticalTool(MGCommandStateOwner* owner)
:MGLocateState(owner,UNLOCK_SNAP_ATTRIB,LINE_RUBBER,POINT_IPDRAW),
m_dRadius(dRadius), m_bRound(false){
}

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

bool MGRectVerticalTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_dRadius = pref.GetDoubleValue(upv_Curve_RectVertical_Radius);
	//m_dRho = pref.GetDoubleValue(upv_Curve_RectVertical_Rho);
	//m_bCircle = pref.GetBoolValue(upv_Curve_RectVertical_Circle);
	return false;
}

bool MGRectVerticalTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetDoubleValue(upv_Curve_RectVertical_Radius, m_dRadius);
	//pref.SetDoubleValue(upv_Curve_RectVertical_Rho, m_dRho);
	//pref.SetBoolValue(upv_Curve_RectVertical_Circle, m_bCircle);

	return MGLocateState::terminate_tool(cancel);
}

///make m_rect from input 0,1 data and posLas.
void MGRectVerticalTool::make_rect(
	const MGPosition& posLast
){
	const LInfoVec& linfos=locates();
	assert(linfos.size()>=2);

	size_t np=linfos.size();
	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1=linfos[1]->point_world();
	m_rect.create_from_edge(P0, P1, posLast);
}

///make m_round_rect from m_rect and poslLast.
void MGRectVerticalTool::make_round_rect(
	const MGPosition& posLast
){
	m_round_rect.create(&m_rect,posLast);
}

///make m_round_rect from m_rect and radius.
void MGRectVerticalTool::make_round_rect(
	double radius
){
	m_round_rect.create(&m_rect,radius);
}

void MGRectVerticalTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	const LInfoVec& linfos=locates();
	size_t np=linfos.size();
	if(np==2){
		make_rect(cursor());
	}else if(np==3){
		make_round_rect(cursor());
	}
	MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
	if(m_round_rect.valid()){
		m_round_rect.draw(sgl);
	}else if(m_rect.valid()){
		m_rect.draw(sgl);
	}
}

bool MGRectVerticalTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	LInfoVec& linfos=locates();
	switch(nChar){
	case 'r':
	case 'R':
		// round option
		if(linfos.empty() && !m_bRound){
			m_bRound = true;
		}else if(linfos.size()==3 && m_bRound){
			// 数値入力(real)
			CString Title;
			Title.LoadString(IDS_CAPTION_CORNER_R);
			CGLInputRealDlg dlg(Title);
			dlg.SetValue(m_dRadius);
			if(dlg.DoModal()==IDOK){
				double x = dlg.GetValue();
				if(x>0){
					m_dRadius=x;
					make_round_rect(x);
					// ドキュメント変更
					add_object_to_current_group(m_bRound ? m_round_rect.release() : m_rect.release());
					return OnCommandEnd(1);
				}
			}
		}
		break;
	case VK_RETURN:
		if(linfos.size() == 2){
			disable_AETPmode();

			const MGPlane& pl = linfos[0]->window()->cplane().plane();
			const MGPosition& P0=linfos[0]->point_world();
			MGLocateInfo& linf1=*linfos[1];
			const MGPosition& P1=linf1.point_world();
			// 長方形のもう一辺の長さを len(ipos[0], ipos[1]) とする。
			const double dDist = P0.distance(P1);
			MGPosition P2 = (P0+P1)*.5 + dDist*pl.normal();
			make_rect(P2);
			if(!m_bRound){
				// ドキュメント変更
				add_object_to_current_group(m_rect.release());
				return OnCommandEnd(1);
			}

			///Simulate that P2 is input as the 3rd point when m_bRound==true.
			MGLocateInfo* linfP2=new MGLocateInfo(linf1);//CPoint data is invalid.
			linfP2->point_world()=P2;
			linfos.emplace_back(linfP2);
		}
		prompt_message();
		draw_temporary();
		return false;
	default:;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGRectVerticalTool::OnLocated(const MGLocateInfo& info){
	const LInfoVec& linfos=locates();
	size_t np = linfos.size();
	if(np==1){
		m_rect.clear();
		m_round_rect.clear();
		set_rubberband_kind(LINE_RUBBER);
	}
	if(np==2){
		MGLocateInfo& linf0=*linfos[0];
		const MGPosition& P0=linf0.point_world();
		const MGPosition& P1=linfos[1]->point_world();
		MGPosition Pmid=(P0+P1)*.5;
		const MGVector& normal=linf0.window()->cplane().plane().normal();
		setElevationRestrictionToProhibitUpdate(Pmid, normal);
		m_round_rect.clear();
	}else
		disable_AETPmode();

	if(np>=2)
		set_rubberband_kind(NO_RUBBER);

	if(!m_bRound){//not round rect,.
		if(np>=3){//make rect from 3rd point.
			// ドキュメント作成
			make_rect(linfos[2]->point_world());
			add_object_to_current_group(m_rect.release());
			return OnCommandEnd(1);
		}
	}else{//round rect
		if(np==3){
			make_rect(linfos[2]->point_world());
		}else if(np>=4){
			make_round_rect(linfos[3]->point_world());
			add_object_to_current_group(m_round_rect.release());
			return OnCommandEnd(1);
		}
	}

	return false;
}

void MGRectVerticalTool::prompt_message() const{
	switch(locates().size()){
	case 0:
		{
			UINT nIDS = m_bRound
				? IDS_PROMPT_RECT_POINT_START_NO_R : IDS_PROMPT_RECT_POINT_START_R;
			SetStatusMessage(nIDS);
		}
		break;
	case 1:
		SetStatusMessage(IDS_PROMPT_RECT_POINT_END);
		break;
	case 2:
		SetStatusMessage(IDS_PROMPT_RECT_POINT_BROAD);
		break;
	case 3:
		{
			SetStatusMessage(IDS_PROMPT_RECT_ROUND, m_dRadius);
		}
		break;
	}
}
