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

/**
 * @file SurfKnotInsert.h
 * @brief MGSurfKnotInsertTool クラスのインターフェイス
 */
#if !defined(AFX_SURFKNOTINSERT_H__2A99D2E1_2B3B_40D8_AC15_99A92EA0BF55__INCLUDED_)
#define AFX_SURFKNOTINSERT_H__2A99D2E1_2B3B_40D8_AC15_99A92EA0BF55__INCLUDED_

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

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

/// @class MGSurfKnotInsertTool SurfKnotInsert.h SurfCmd/SurfKnotInsert.h
/// 
/// 面上のパラメータを指定してノットを追加するコマンドを実現する。
class MGSurfKnotInsertTool : public MGCommandStateOwner{
public:
	explicit MGSurfKnotInsertTool(fugenDoc* pDoc);
	virtual MGCommandBase* initial_clone(fugenDoc* pDoc)const;
	virtual bool initiate_tool();
	virtual bool 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=true);
	void display(mgSysGL& sgl,fugenView* pView);

private:
	bool calculate();

	MGPickObject m_surf; ///< ターゲットとなるsurface
	std::vector<UniqueCurve> m_ilines; ///< initial parameter lines.

	int m_direction; ///< parameter direction, 0:u=const, 1:v=const, 2=both.
	std::vector<MGPosition> m_uvs; ///< Located (u,v) parameter of m_surf;
	std::vector<int> m_directions; ///< [i] is the parameter direction of m_uvs[i].
	std::vector<UniqueCurve> m_plines; ///< temporary generated parameter lines.

	MGPosition m_uv; ///< current(mouse position's) surface parameter.
	UniqueCurve m_uline; ///< v=const, u-parameter line for the cursor.
	UniqueCurve m_vline; ///< u=const, v-parameter line for the cursor.

	friend class MGSurfKnotInsertSSurf;
	friend class MGSurfKnotInsertIPoint;
};

/// @class MGSurfKnotInsertSSurf
/// 
/// 素の曲面をひとつだけ選択させる。plane はアウト。
class MGSurfKnotInsertSSurf : public MGSelectState{
public:
	MGSurfKnotInsertSSurf(MGSurfKnotInsertTool* owner);

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

	virtual bool initiate_tool();
	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).
		);
};

/// @class MGSurfKnotInsertIPoint
/// 
/// マウスの動いている場所が曲面上に投影可能であれば、
/// その位置にノットを追加する
class MGSurfKnotInsertIPoint : public MGLocateOnObjects{
public:
	MGSurfKnotInsertIPoint(MGSurfKnotInsertTool* owner);

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

	virtual bool initiate_tool();
	virtual bool OnKeyDown(fugenView* pView, UINT nChar, UINT nRepCnt, UINT nFlags);
	virtual bool OnLocated(const MGLocateInfo& info);
	virtual void do_make_temporary_display(mgSysGL& sgl,fugenView* pView);

private:
	void prompt_message() const;
};

#endif // !defined(AFX_SURFKNOTINSERT_H__2A99D2E1_2B3B_40D8_AC15_99A92EA0BF55__INCLUDED_)
