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

/**
 * @file Parabola.cpp
 * @brief MGParabolaTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "Calc/mgcalc.h"
#include "Calc/conic.h"
#include "fugenView.h"
#include "Misc/UserPreference.h"
#include "CurveCmd/Parabola.h"

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

// MGParabolaTool

MGParabolaTool::MGParabolaTool(fugenDoc* pDoc)
:MGLocateState(pDoc,ID_CURVE_PARABOLA,NO_RUBBER,POINT_IPDRAW),m_nIDS(1),m_bHalf(false){
}

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

bool MGParabolaTool::initiate_tool(){
	MGLocateState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_bHalf = pref.GetBoolValue(upv_Curve_Parabola_Half);
	return false;
}

bool MGParabolaTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetBoolValue(upv_Curve_Parabola_Half, m_bHalf);
	return MGLocateState::terminate_tool(cancel);
}

bool MGParabolaTool::calculate(){
	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();
	m_parabola =mgcalc::create_parabola(
		P0, // vertex
		P1-P0, // as direction (MGVector)
		P2,
		m_bHalf);
	
	if(!m_parabola.get()){
		// failure
		m_nIDS = IDS_FAIL_GENERATE_CURVE;
		return false;
	}else{
		add_object_to_current_group(m_parabola.release());
	}

	return true;
}

void MGParabolaTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	const LInfoVec& linfos=locates();
	size_t np = linfos.size();
	if(np==0)
		return;

	const MGPosition& P0=linfos[0]->point_world();
	MGColor::get_instance(MGColor::White).exec(sgl);
	if(np<2){
		m_parabola.reset();
		sgl.drawStraight(P0,cursor());
	}else{
		const MGPosition& P1=linfos[1]->point_world();
		sgl.drawStraight(P0, P1);

		m_parabola = mgcalc::create_parabola(
			P0, // vertex
			P1-P0, // as direction (MGVector)
			cursor(),
			m_bHalf);
		if(m_parabola.get()){
			MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
			m_parabola->drawWire(sgl);
		}
	}	
}

bool MGParabolaTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'h':
	case 'H':
		m_bHalf = !m_bHalf;
		break;
	default:;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

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

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

void MGParabolaTool::prompt_message() const{
	CString strHalfYN;
	strHalfYN.LoadString(m_bHalf ? IDS_YES : IDS_NO);
	switch(locates().size()){
	case 0:
		SetStatusMessage(
			IDS_PROMPT_CURVE_PARABOLA_VERTEX,strHalfYN);
		break;
	case 1:
		SetStatusMessage(
			IDS_PROMPT_CURVE_PARABOLA_DIRECTION,
			strHalfYN);
		break;
	case 2:
		SetStatusMessage(
			IDS_PROMPT_CURVE_PARABOLA_END,
			strHalfYN);
		break;
	}
}
