/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/********************************************************************/
/**
 * @file TrimTool.h
 * @brief クラス MGTrimTool の宣言
 */
#if !defined(AFX_TRIMTOOL_H__8C474FDD_FD31_4670_8608_AD6CBA994197__INCLUDED_)
#define AFX_TRIMTOOL_H__8C474FDD_FD31_4670_8608_AD6CBA994197__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Common/CommandStateOwner.h"
#include "Common/SelectState.h"

/// @class MGTrimTool TrimTool.h "EditCmd/TrimTool.h"
///
/// Trims an object.
/// Curves and surfaces can be trimmed with curves, surfaces, faecs.
///
/// When you trim a surface with a curve in a plane parallel view 
/// like the fugenView2Dxy, fugenView2Dyz, and fugenView2Dxz view, 
/// the cutting curve is projected onto the surface in the view direction.
///
/// When you trim a surface with a 3-D curve in an angled parallel
/// or a perspective view, the cutting curve is projected onto the surface
/// normally.
///
/// @note 仕様は doc/edit-trim.doc にある。
class MGTrimTool : public MGCommandStateOwner
{
	/// トリムに使うオブジェクト(Trimmer)
	//@{
	MGPickObjects m_Ctrimmers; ///< MGCurve: surfをトリムするものとして使用
	MGPickObjects m_Strimmers; ///< MGFSurface: トリムされるオブジェクトとして使用
	//@}

	/// コマンドオプション
	//@{
	bool m_bExtend; ///< カッターカーブの両端を適宜延長するか。
	bool m_bApparent; ///< 仮想交差ロジックを適用するか。
	bool m_bExtract;///<true=抽出、false=trim
	//@}

public:
	explicit MGTrimTool(fugenDoc* pDoc);

	virtual MGCommandBase* initial_clone(fugenDoc* pDoc)const;
	virtual bool initiate_tool();
	virtual bool OnCommandCanceled(UINT nIDS);

	enum OptionName{
		EXTEND,
		APPARENT,
		EXTRACT
	};
	bool IsExtract()const{return m_bExtract;};
	bool IsEnabled(OptionName opt) const;
	void ToggleExtendOption();
	void ToggleApparentOption();
	void ToggleExtractOption();

	void prompt_message(UINT nIDS)const;

	/// 選択オブジェクトの仕分けを行う。
	/// @return 切断オブジェクトが定義できたら true を返す。
	///
	/// 1. 切断オブジェクトとして不適当なタイプのものを選択オブジェクトから除外する。
	/// 2. このクラスのメンバーデータを適宜セットする。
	bool FilterForTrimmer();

	/// ターゲットに切断オブジェクトが含まれていればそれを除外する。
	/// @param [in,out] target トリム対象オブジェクト候補。
	void ExcludeTrimmer(MGPickObjects& target);

	/// トリムを実行する。
	/// @param[in] target トリムターゲット。
	/// @param[in] pView トリムイベントが発生したビュー。
	/// @return トリム操作が実際に発生したら true を返す。
	bool Execute(
		MGPickObject& target,
		fugenView* pView);
};

/// @class MGTrimSelTrimmer
///
/// トリムに使うオブジェクトを選択する state
/// @note 仕様書の [S1] に相当する状態を表現する。
class MGTrimSelTrimmer : public MGSelectState{
public:
	MGTrimSelTrimmer(MGTrimTool* owner);

	MGTrimTool* state_owner(){
		return static_cast<MGTrimTool*>(get_owner_command());
	}
	const MGTrimTool* state_owner()const{
		return static_cast<const MGTrimTool*>(get_owner_command());
	}

	virtual bool initiate_tool();
	virtual bool OnKeyDown(fugenView* window, UINT nChar,UINT nRepCnt, UINT nFlags);
	virtual bool 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).
		);

private:
	void prompt_message()const;
};

/// @class MGTrimSelTarget
///
/// トリムされるオブジェクトを選択する state
/// @note 仕様書の [S2] に相当する状態を表現する。
class MGTrimSelTarget : public MGSelectState{
public:
	MGTrimSelTarget(MGTrimTool* owner);

	MGTrimTool* state_owner(){
		return static_cast<MGTrimTool*>(get_owner_command());
	}
	const MGTrimTool* state_owner()const{
		return static_cast<const MGTrimTool*>(get_owner_command());
	}

	virtual bool initiate_tool();
	virtual bool OnKeyDown(fugenView* window, UINT nChar,UINT nRepCnt, UINT nFlags);
	virtual bool 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).
		);

private:
	void prompt_message()const;
};

#endif // !defined(AFX_TRIMTOOL_H__8C474FDD_FD31_4670_8608_AD6CBA994197__INCLUDED_)
