/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/**
 * @file SurfOffsetTool.cpp
 * @brief MGSurfOffsetTool クラスのインプリメンテーション
 */
#include "stdafx.h"
#include "fugen.h"
#include "fugenDoc.h"
#include "fugenView.h"
#include "SurfCmd/SurfOffsetTool.h"
#include "GLInputRealDlg.h"
#include "Calc/mgcalc.h"
#include "Calc/mgfunctor.h"
#include "Misc/UserPreference.h"

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

namespace{
	const double dOffset = 1.0;
}

// MGSurfOffsetTool

MGSurfOffsetTool::MGSurfOffsetTool(fugenDoc* pDoc)
	 : MGSelectState(
		 pDoc,
		 ID_SURFACE_OFFSET,
		 MULTIPLE_SELECT, // multiple-selection
		 mgAll_FSurface),
	   m_dOffset(dOffset)
{
}

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

bool MGSurfOffsetTool::initiate_tool(){
	MGSelectState::initiate_tool();
	const UserPreference& pref = UserPreference::getInstance();
	m_dOffset = pref.GetDoubleValue(upv_Surface_Offset_Distance);

	// 選択モデルからsurface/faceを選別
	m_srf = select_from_current_objects(mgAll_FSurface);
	if(!m_srf.empty()){

		// オフセットパラメータを入力
		draw_temporary();
		if(!input_param()){
			return OnCommandEnd(3);
		}
		return OnCommandEnd(1);
	}
	else{
		// 余分な選択を解除
		clear_pick_object();

		// 最初のメッセージ
		SetStatusMessage(IDS_PROMPT_SURFACE);
	}
	return false;
}

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

	return MGSelectState::terminate_tool(cancel);
}

bool MGSurfOffsetTool::input_param(){
	SetStatusMessage(IDS_CAPTION_OFFSET_RADIUS);
	CString str;
	str.Format(IDS_CAPTION_OFFSET_RADIUS);

	CGLInputRealDlg dlg(str);
	dlg.SetValue(m_dOffset);
	::ReleaseCapture();
	
	bool bOK = (IDOK == dlg.DoModal());
	if(bOK){
		m_dOffset = dlg.GetValue();
	}
	return bOK;
}

bool MGSurfOffsetTool::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
){
	// 処理中メッセージ
	SetStatusMessage(IDS_PROMPT_COMPUTE);
	CWaitCursor sangglass;

	const double radius = m_dOffset;
	MGGelPositions gelps;

	MGPickObjects::iterator cur = m_srf.begin(), last = m_srf.end();
	for(; cur != last; ++cur){
		int err = 0;
		std::vector<UniqueFSurface> result;
		err = (*cur)->top_object()->fsurface()->offset_fs(radius, result);
		if(!err){
			MGGroup* grp = (*cur)->bottom_group();
			for (auto i = result.begin(), iend = result.end(); i != iend; i++)
				gelps.push_back(MGGelPosition(grp, i->release()->object_pointer()));
		}
	}

	add_object_to_document(gelps);
	return MGSelectState::OnCommandEnd(1);
}

bool MGSurfOffsetTool::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_srf = select_from_current_objects(mgAll_FSurface);
	if(!m_srf.empty()){
		draw_temporary();
		if(!input_param()){
			// キャンセルされた
			return OnCommandEnd(3);
		}
	}
	else{
		return false;
	}
	// オフセットして終了
	return OnCommandEnd(1);
}
