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

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

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

// MGExtendLineToPnt

MGExtendLineToPnt::MGExtendLineToPnt(fugenDoc* pDoc)
: MGLocateState(pDoc,ID_CURVE_EXTEND_LINE,NO_RUBBER,NO_IPDRAW),
m_nIDS(1), m_bBoth(false){
	// near が必須となる
	turn_on_near();
}

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

bool MGExtendLineToPnt::initiate_tool(){
	MGLocateState::initiate_tool();
	UserPreference& pref = UserPreference::getInstance();
	m_bBoth = pref.GetBoolValue(upv_Curve_ExtendLineToPoint_Both);

	// クリアも必須
	clear_pick_object();
	return false;
}

bool MGExtendLineToPnt::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetBoolValue(upv_Curve_ExtendLineToPoint_Both, m_bBoth);
	return MGLocateState::terminate_tool(cancel);
}

bool MGExtendLineToPnt::calculate(){
	// 1. 延長部分の決定
	const MGLocateInfo& info=*(locates()[0]);
	const MGCurve* curve=static_cast<const MGCurve*>(info.object());
	std::unique_ptr<MGCurve> line=mgcalc::create_line_by_extension(
		*curve,info.curve_parameter(),locates().back()->point_world(),m_bBoth);
	if(!line.get()){
		// failed
		m_nIDS = IDS_FAIL_GENERATE_CURVE;
		return false;
	}

	// 2. 両方向オプションが OFF の場合には結合し、
	// ON の場合には単に新要素の作成とする。
	if(m_bBoth){
		add_object_to_current_group(line.release());
	}else{
		std::unique_ptr<MGCurve> compo(mgcalc::connect(*curve, *line.get()));
		if(!compo.get()){
			// failed
			return false;
		}
		// やむを得ぬconst_cast
		replace_object(const_cast<MGCurve*>(curve), compo.release());
	}
	return true;
}

void MGExtendLineToPnt::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	if(locates().empty()){
		return;
	}

	const MGLocateInfo& info=*(locates()[0]);
	if(info.is_deleted()){
		return;
	}

	const MGCurve* curve=static_cast<const MGCurve*>(info.object());
	std::unique_ptr<MGCurve> line
		=mgcalc::create_line_by_extension(*curve,info.curve_parameter(),cursor(),m_bBoth);

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

bool MGExtendLineToPnt::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'b':
	case 'B':
		if(locates().size()==1){
			m_bBoth = !m_bBoth;
		}
		 break;
	default:;
	}
	return MGLocateState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
}

bool MGExtendLineToPnt::OnLocated(const MGLocateInfo& info){
	if(info.is_deleted()){
		return false;
	}

	if(locates().size()==1){
		const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
		if(!curve){
			cancel_last_locate();
		}
		return false;
	}

	// 延長点が入力された
	if(!calculate()){
		// failed
		return OnCommandEnd(m_nIDS);
	}
	return OnCommandEnd(1);
}

void MGExtendLineToPnt::prompt_message() const{
	if(locates().size()<1)
		SetStatusMessage(IDS_PROMPT_CURVE_END);
	else{
		CString strYesNo;
		strYesNo.LoadString(m_bBoth ? IDS_YES : IDS_NO);
		SetStatusMessage(IDS_PROMPT_LINE_END, strYesNo);
	}
}
