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

// Conic.cpp: MGConicTool クラスのインプリメンテーション

#include "stdafx.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "GLInputRealDlg.h"
#include "Calc/conic.h"
#include "Calc/mgcalc.h"
#include "Misc/UserPreference.h"
#include "CurveCmd/Conic.h"

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

// MGConicTool

MGConicTool::MGConicTool(fugenDoc* pDoc)
:MGLocateState(pDoc, ID_CURVE_CONIC, NO_RUBBER, POINT_IPDRAW),
 m_rho(-1.)  // 無効値でスタート
{
}

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

bool MGConicTool::initiate_tool(){
	MGLocateState::initiate_tool();
	UserPreference& pref = UserPreference::getInstance();
	m_rho = pref.GetDoubleValue(upv_Curve_Conic_Rho);
	return false;
}

bool MGConicTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetDoubleValue(upv_Curve_Conic_Rho, m_rho);

	return MGLocateState::terminate_tool(cancel);
}

std::unique_ptr<MGCurve> MGConicTool::makeModel(const MGPosition& P3){
	const LInfoVec& linfos=locates();
	const MGPosition& P0=linfos[0]->point_world();
	const MGPosition& P1=linfos[1]->point_world();
	const MGPosition& P2=linfos[2]->point_world();
	std::unique_ptr<MGCurve> curve;
	// 1. 円錐曲線を計算する
	if(m_rho < 0.){
		curve=mgcalc::create_conic_curve(P0,P1,P2,m_rho);
	}else{
		curve=mgcalc::create_conic_curve(P0,P1,P2,P3);
	}
	return curve;
}


void MGConicTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	MGColor::get_instance(MGColor::White).exec(sgl);
	const LInfoVec& linfos=locates();
	switch(linfos.size()){
	case 0:
		// 何も書かない
		break;
	case 1:
		sgl.drawStraight(linfos[0]->point_world(), cursor());
		break;
	case 2:{
			const MGPosition& P0=linfos[0]->point_world();
			const MGPosition& P1=linfos[1]->point_world();
			sgl.drawOpenPolyline(&P0,&cursor(),&P1,nullptr);
		}
		break;
	case 3:{
			const MGPosition& P0=linfos[0]->point_world();
			const MGPosition& P1=linfos[1]->point_world();
			const MGPosition& P2=linfos[2]->point_world();

			sgl.drawOpenPolyline(&P0,&P2,&P1,nullptr);
			std::unique_ptr<MGCurve> curve=makeModel(cursor());
			if(curve.get()){
				MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
				curve->drawWire(sgl);
			}
		}
		break;
	}
}

bool MGConicTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	const LInfoVec& linfos=locates();
	switch(nChar){
	case 'r':
	case 'R':
		// rho 値の設定
		if(linfos.size() == 3){
			CGLInputRealDlg dlg;
			dlg.SetValue(m_rho);
			if(IDOK == dlg.DoModal()){
				double d = dlg.GetValue();
				pView->SetFocus();
				if(0<d && d<1){
					m_rho = d;
					// ここで終了する
					std::unique_ptr<MGCurve> curve=makeModel(cursor());//cursor() is not used.
					if(!curve.get()){
						return OnCommandEnd(IDS_FAIL_GENERATE_CURVE);
					}else{
						add_object_to_current_group(curve.release());
						return OnCommandEnd(1);
					}
				}
			}
			pView->SetFocus();
		}
		break;
	default:
		;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGConicTool::OnLocated(const MGLocateInfo& info){
	LInfoVec& linfos=locates();
	size_t np=linfos.size();
	if(np>=2){
		const MGPosition& P0=linfos[0]->point_world();
		const MGPosition& P1=linfos[1]->point_world();
		if(linfos.size()==3){
			const MGPosition& P2=linfos[2]->point_world();
			// 軸上に input されないように
			if((P1-P0).parallel(P2-P1) || P0==P2){
				cancel_last_locate();
			}
		}
	}
	if(linfos.size()<4){
		// 再描画
		return false;
	}

	const MGPosition& P3=linfos[3]->point_world();
	std::unique_ptr<MGCurve> curve=makeModel(P3);
	UINT nIDS=IDS_FAIL_GENERATE_CURVE;
	if(curve.get()){
		nIDS=1;
		add_object_to_current_group(curve.release());
	}
	return OnCommandEnd(nIDS);
}

void MGConicTool::prompt_message() const{	
	const LInfoVec& linfos=locates();
	UINT nIDS;
	switch(linfos.size()){
	case 0:
		nIDS = IDS_PROMPT_CONIC_START;
		break;
	case 1:
		nIDS = IDS_PROMPT_CONIC_END;
		break;
	case 2:
		nIDS=IDS_PROMPT_CONIC_APEX;
		break;
	case 3:
		nIDS=IDS_PROMPT_CONIC_CURVA;
		break;
	}
	SetStatusMessage(nIDS);
}
