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

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

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

// MGCurveOffsetTool

MGCurveOffsetTool::MGCurveOffsetTool(fugenDoc* pDoc)
: MGSelectState(pDoc, ID_CURVE_OFFSET,
		 MULTIPLE_SELECT, // multiple selection
		 mgAll_Curve),
	   m_dOffset(1.0)
{
}

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

bool MGCurveOffsetTool::initiate_tool(){
	MGSelectState::initiate_tool();
	UserPreference& pref = UserPreference::getInstance();
	m_dOffset = pref.GetDoubleValue(upv_Curve_Offset_Distance);

	// 選択モデルから曲線を選別
	m_curve = select_from_current_objects(mgAll_Curve);
	if(!m_curve.empty()){
		set_current_object(m_curve);
	}else{
		// 余分な選択を解除
		clear_pick_object();
	}

	// 最初のメッセージ
	prompt_message();
	UpdatePreview();
	return false;
}

bool MGCurveOffsetTool::terminate_tool(bool cancel){
	UserPreference& pref = UserPreference::getInstance();
	pref.SetDoubleValue(upv_Curve_Offset_Distance, m_dOffset);

	return MGSelectState::terminate_tool(cancel);
}

void MGCurveOffsetTool::do_make_temporary_display(mgSysGL& sgl,fugenView* pView){
		MGColor::get_instance(MGColor::SpringGreen).exec(sgl);
		auto drawObj = mgcalc::CreateDrawFunctor(sgl);
		for(auto& prev:m_preview)
			drawObj(prev.get());
}

bool MGCurveOffsetTool::input_param(){
	SetStatusMessage(IDS_CAPTION_OFFSET_RADIUS);

	CString str;
	VERIFY(str.LoadString(IDS_CAPTION_OFFSET_RADIUS));

	CGLInputRealDlg dlg(str);
	dlg.SetValue(m_dOffset);

	bool bOK = (IDOK == dlg.DoModal());
	if(bOK){
		m_dOffset = dlg.GetValue();
	}
	return bOK;
}

bool MGCurveOffsetTool::OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags){
	switch(nChar){
	case 'd':
	case 'D':
		// 距離入力
		input_param();
		// 更新
		pView->SetFocus();
		prompt_message();
		UpdatePreview();
		return false;
	default:
		return MGSelectState::OnKeyDown(pView, nChar, nRepCnt, nFlags);
	}
}

bool MGCurveOffsetTool::calculate(){
	// 処理中メッセージ
	SetStatusMessage(IDS_PROMPT_COMPUTE);
	MGGelPositions gelps;
	for (auto& gelp : m_curve) {
		const MGCurve* curve = dynamic_cast<const MGCurve*>(gelp->top_object());
		std::vector<UniqueCurve> crvs = curve->offset(m_dOffset);
		for(auto& crv:crvs)
			gelps.append(MGGelPosition(gelp->bottom_group(), crv.release()));
	}
	add_object_to_document(gelps);
	return true;
}

bool MGCurveOffsetTool::OnCommandEnd(
	UINT nIDS,
	bool erase_temporary_display)
{
	// オフセットして終了
	if(!calculate()){
		return MGSelectState::OnCommandEnd(2);
	}

	return MGSelectState::OnCommandEnd(nIDS, erase_temporary_display);
}

bool MGCurveOffsetTool::OnSelected(
	fugenView* window,//The fugenView pointer where point input event took place.
	MGPickObjects&	objs,	//selected objects at this selection operation.
	MGPickObjects&	unselected_objects	//unselected objects at this selection operation.
		//unselected_objects.size()>=1 only when the already selected objects are selected
		//when add mode is set(or when operation is done with a crtl key pressed).
){
	m_curve = select_from_current_objects(mgAll_Curve);
	if(!m_curve.empty()){
		set_current_object(m_curve);
	}

	UpdatePreview();
	return false;
}

void MGCurveOffsetTool::UpdatePreview(){
	m_preview.clear();
	for(auto& gelp:m_curve){
		const MGCurve* curve = dynamic_cast<const MGCurve*>(gelp->top_object());
		std::vector<UniqueCurve> crvs = curve->offset(m_dOffset);
		std::move(crvs.begin(), crvs.end(), std::back_inserter(m_preview));
	}
	draw_temporary();
}

void MGCurveOffsetTool::prompt_message()const{
	SetStatusMessage(IDS_PROMPT_CURVE_OFFSET, m_dOffset);
}
