/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/* ***************************************************** */
/********************************************************************/
/**
 * @file ExtendLengthTool.cpp
 * @brief MGExtendLengthTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "Calc/curve.h"
#include "Calc/mgcalc.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "GLCurveExtendDlg.h"
#include "CurveCmd/ExtendLengthTool.h"

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

// MGExtendLengthTool

MGExtendLengthTool::MGExtendLengthTool(fugenDoc* pDoc)
: MGLocateState(pDoc,ID_CURVE_EXTEND,NO_RUBBER,POINT_IPDRAW){
	// ダイアログを準備する
	attachModelessDialogue<CGLCurveExtendDlg>(this);

	turn_on_near();
	turn_on_end();
}

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

bool MGExtendLengthTool::initiate_tool(){
	MGLocateState::initiate_tool();
	// 強制的にクリア
	clear_pick_object();
	return false;
}

void MGExtendLengthTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
	if(!m_spPreview.get()){
		return;
	}

	MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
	m_spPreview->drawWire(sgl);
}

bool MGExtendLengthTool::OnCommandCanceled(UINT nIDS){
	clear_pick_object();
	return MGLocateState::OnCommandCanceled(nIDS);
}

bool MGExtendLengthTool::OnCommandEnd(
	UINT nIDS,	//=0: erase the current message, and display no messages.
				//=1: display "xxxx" normally end.
				//otherwise: nIDS is a string id, and load the message from string table to display.
	bool erase_temporary_display
){
	if(!GetTargetCurve()){
		// 入力がないのでキャンセルだろう。
		return OnCommandCanceled(1);
	}

	std::unique_ptr<MGCurve> ext(ExtendCurve());
	if(!ext.get()){
		// failed
		return OnCommandCanceled(IDS_FAIL_GEL_REPLACE);
	}

	if(!ext.get() || !replace_object(GetTargetCurve(), ext.release())){
		// failed
		return OnCommandCanceled(IDS_FAIL_GEL_REPLACE);
	}
	return MGLocateState::OnCommandEnd(nIDS);
}

MGCurve* MGExtendLengthTool::GetTargetCurve() const{
	const LInfoVec& linfos = locates();
	return linfos.empty() ? 0 : dynamic_cast<MGCurve*>(linfos.back()->object());
}

MGCurve* MGExtendLengthTool::ExtendCurve() const{
	const LInfoVec& linfos=locates();
	if(linfos.empty())
		return 0;

	const MGCurve* curve = GetTargetCurve();

	// ピック位置に相当する曲線パラメーター
	MGLocateInfo& info = *linfos.back();
	const double t = info.curve_parameter();

	const CGLCurveExtendDlg& dialog=*getCurveExtendDialog();

	// このチェックは重要
	const double dLength = dialog.GetLength();
	if(dLength < MGTolerance::wc_zero()){
		return 0;
	}

	// 曲率変化
	const double dVary = dialog.GetVary();

	return mgcalc::extend(*curve, t, dLength, dVary);
}

bool MGExtendLengthTool::OnLocated(const MGLocateInfo& info){
	const MGCurve* curve = dynamic_cast<const MGCurve*>(info.object());
	if(!curve){
		cancel_last_locate();
		prompt_message();
		return false;
	}

	CGLCurveExtendDlg& dialog=*getCurveExtendDialog();

	// UI 的に不自然なのだが、
	// 曲線の全長の 1/5 程度の値をプリセット値とする。
	dialog.SetLength(curve->length() * .2);
	dialog.UpdateData(FALSE);

	// ダイアログ表示
	if(!dialog.IsWindowVisible()){
		CPoint pt;
		::GetCursorPos(&pt);
		pt.Offset(-4, -4);
		dialog.SetWindowPos(&CWnd::wndTop, pt.x, pt.y, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
	}

	// プレビューも用意
	UpdateView();
	return false;
}

void MGExtendLengthTool::UpdateView(){
	m_spPreview.reset(ExtendCurve());
	draw_temporary();
}

void MGExtendLengthTool::prompt_message() const{
	if(locates().size()==0){
		SetStatusMessage(IDS_PROMPT_CURVE_END);
	}else{
		SetStatusMessage(IDS_PROMPT_LENGTH);
	}
}

CGLCurveExtendDlg* MGExtendLengthTool::getCurveExtendDialog(){
	return static_cast<CGLCurveExtendDlg*>(getModelessDialogPointer());
}
const CGLCurveExtendDlg* MGExtendLengthTool::getCurveExtendDialog()const{
	return static_cast<const CGLCurveExtendDlg*>(getModelessDialogPointer());
}