/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/********************************************************************/
/**
 * @file fugenDoc.cpp
 * @brief クラス fugenDoc の宣言。
 *
 * クラスのボリュームが大きいので、ファイルをいくつかに分けている。
 * このファイルはコマンドハンドラーマップと OnCmdMsg の実装のみとする。
 */
#include "stdafx.h"
#include "fugen.h"
#include "fugenDoc.h"

#include "Common/GLCommandFactory.h"
#include "Common/CommandBase.h"

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

/////////////////////////////////////////////////////////////////////////////
// fugenDoc

IMPLEMENT_DYNCREATE(fugenDoc, CDocument)

BEGIN_MESSAGE_MAP(fugenDoc, CDocument)
	//{{AFX_MSG_MAP(fugenDoc)

	// ファイル
	//@{
	ON_COMMAND(ID_FILE_SEND_MAIL, CDocument::OnFileSendMail)

	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
	ON_UPDATE_COMMAND_UI(ID_FILE_SEND_MAIL, CDocument::OnUpdateFileSendMail)
	//@}

	// 編集
	//@{
	ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
	ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
	ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)

	// 編集＞オブジェクトを選択
	//@{
	ON_COMMAND(ID_SELECT_ALL, OnSelectAll)
	ON_COMMAND(ID_SELECT_CLEAR, OnSelectClear)
	ON_COMMAND(ID_SELECT_INVERT, OnSelectInvert)
	ON_COMMAND(ID_SELECT_LAST, OnSelectLast)
	ON_COMMAND(ID_SELECT_POINT, OnSelectPoint)
	ON_COMMAND(ID_SELECT_CURVE, OnSelectCurve)
	ON_COMMAND(ID_SELECT_SURFACE, OnSelectSurface)
	ON_COMMAND(ID_SELECT_SHELL, OnSelectShell)
	ON_COMMAND(ID_SELECT_MESH, OnSelectMesh)

	ON_UPDATE_COMMAND_UI(ID_SELECT_ALL, OnUpdateSelectAll)
	ON_UPDATE_COMMAND_UI(ID_SELECT_CLEAR, OnUpdateSelectClear)
	ON_UPDATE_COMMAND_UI(ID_SELECT_INVERT, OnUpdateSelectInvert)
	ON_UPDATE_COMMAND_UI(ID_SELECT_LAST, OnUpdateSelectLast)
	ON_UPDATE_COMMAND_UI(ID_SELECT_POINT, OnUpdateSelectPoint)
	ON_UPDATE_COMMAND_UI(ID_SELECT_CURVE, OnUpdateSelectCurve)
	ON_UPDATE_COMMAND_UI(ID_SELECT_SURFACE, OnUpdateSelectSurface)
	ON_UPDATE_COMMAND_UI(ID_SELECT_SHELL, OnUpdateSelectShell)
	ON_UPDATE_COMMAND_UI(ID_SELECT_MESH, OnUpdateSelectMesh)
	//@}

	// 編集＞表示
	//@{
	ON_COMMAND(ID_DISPLAY_HIDE, OnDisplayHide)
	ON_COMMAND(ID_DISPLAY_SHOW, OnDisplayShow)
	ON_COMMAND(ID_DISPLAY_HIDE_SWAP, OnDisplayHideSwap)
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_HIDE, OnUpdateDisplayHide)
	ON_UPDATE_COMMAND_UI(ID_DISPLAY_SHOW, OnUpdateDisplayShow)
	//@}

	ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
	ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
	ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
	ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateEditClear)
	//@}

	// 表示
	//@{
	ON_COMMAND(ID_ZOOM_EXTENT_ALL_VIEW, OnZoomExtentAllView)
	ON_UPDATE_COMMAND_UI(ID_ZOOM_EXTENT_ALL_VIEW, OnUpdateZoomExtentAllView)
	ON_COMMAND(ID_ZOOM_SELECTED_ALL_VIEW, OnZoomSelectedAllView)
	ON_UPDATE_COMMAND_UI(ID_ZOOM_SELECTED_ALL_VIEW, OnUpdateZoomSelectedAllView)
	ON_COMMAND(ID_VIEWPORT_WIREFRAME, OnViewWireframe)
	ON_UPDATE_COMMAND_UI(ID_VIEWPORT_WIREFRAME, OnUpdateViewWireframe)
	ON_COMMAND(ID_VIEWPORT_SHADE, OnViewShading)
	ON_UPDATE_COMMAND_UI(ID_VIEWPORT_SHADE, OnUpdateViewShading)
	ON_COMMAND(ID_VIEWPORT_WIRE_SHADING, OnViewWireAndShading)
	ON_UPDATE_COMMAND_UI(ID_VIEWPORT_WIRE_SHADING, OnUpdateViewWireAndShading)
	ON_COMMAND(ID_VIEW_PROJECT_XY, OnViewProjectXY)
	ON_COMMAND(ID_VIEW_PROJECT_YZ, OnViewProjectYZ)
	ON_COMMAND(ID_VIEW_PROJECT_ZX, OnViewProjectZX)
	//@}

	// ツール
	//@{
	ON_COMMAND(ID_SNAP_CENTER, OnSnapCenter)
	ON_COMMAND(ID_SNAP_DIALOG, OnSnapDialog)
	ON_COMMAND(ID_SNAP_END, OnSnapEnd)
	ON_COMMAND(ID_SNAP_GRID, OnSnapGrid)
	ON_COMMAND(ID_SNAP_KNOT, OnSnapKnot)
	ON_COMMAND(ID_SNAP_NEAR, OnSnapNear)
	ON_COMMAND(ID_SNAP_VERTEX, OnSnapVertex)

	ON_UPDATE_COMMAND_UI(ID_SNAP_CENTER, OnUpdateSnapCenter)
	ON_UPDATE_COMMAND_UI(ID_SNAP_DIALOG, OnUpdateSnapDialog)
	ON_UPDATE_COMMAND_UI(ID_SNAP_END, OnUpdateSnapEnd)
	ON_UPDATE_COMMAND_UI(ID_SNAP_GRID, OnUpdateSnapGrid)
	ON_UPDATE_COMMAND_UI(ID_SNAP_KNOT, OnUpdateSnapKnot)
	ON_UPDATE_COMMAND_UI(ID_SNAP_NEAR, OnUpdateSnapNear)
	ON_UPDATE_COMMAND_UI(ID_SNAP_VERTEX, OnUpdateSnapVertex)
	//@}

	// 評価
	//@{
	ON_COMMAND(ID_SYSD_KNOTS_NO, OnSysdKnotsNo)
	ON_COMMAND(ID_SYSD_CURVA_OFF, OnSysdCurvaOff)
	//ON_COMMAND(ID_SYSD_CPOLY_OFF, OnSysdCpolyOff)
	ON_UPDATE_COMMAND_UI(ID_EVAL_SNAP_DISPLAY_ON, OnUpdateEvalSnapDisplayOn)
	ON_UPDATE_COMMAND_UI(ID_EVAL_SNAP_DISPLAY_OFF, OnUpdateEvalSnapDisplayOff)
	ON_UPDATE_COMMAND_UI(ID_SYSD_KNOTS_NO, OnUpdateSysdKnotsNo)
	ON_UPDATE_COMMAND_UI(ID_SYSD_CURVA_OFF, OnUpdateSysdCurvaOff)
	//ON_UPDATE_COMMAND_UI(ID_SYSD_CPOLY_OFF, OnUpdateSysdCpolyOff)
	ON_UPDATE_COMMAND_UI(ID_EVAL_SNAP_GEN, OnUpdateEvalSnapGen)
	ON_UPDATE_COMMAND_UI(ID_TESS_WORLD, OnUpdateTessWorld)
	//@}

	// レンダー
	//@{
	//ON_COMMAND(ID_RENDER, OnRender)
	//ON_UPDATE_COMMAND_UI(ID_RENDER, OnUpdateRender)
	//@}
	//}}AFX_MSG_MAP

	ON_BN_CLICKED(IDC_COORD_INPUT, OnCoordInput)
	ON_BN_CLICKED(IDC_CONSTRAINT_DISTANCE_OK, OnConstraintDistance)
	ON_BN_CLICKED(IDC_CONSTRAINT_ANGLE_OK, OnConstraintAngle)
	ON_UPDATE_COMMAND_UI(IDC_COORD_INPUT, OnUpdateCoordInput)
	ON_UPDATE_COMMAND_UI_RANGE(IDC_COORD_X, IDC_COORD_Z, OnUpdateCoordInput)
	ON_UPDATE_COMMAND_UI_RANGE(IDC_CONSTRAINT_DISTANCE, IDC_CONSTRAINT_ANGLE_OK, OnUpdateCoordInput)

	END_MESSAGE_MAP()


BOOL fugenDoc::OnCmdMsg(
	UINT nID,
	int nCode,
	void* pExtra,
	AFX_CMDHANDLERINFO* pHandlerInfo)
{
	// If pHandlerInfo is NULL, then handle the message
	if(!pHandlerInfo){
		// コマンドファクトリーを取得
		CGLCommandFactory& factory = theApp.GetCommandFactory();
		// コマンドが生成可能かテスト
		if(factory.QueryCommand(nID)){
			// メニューアイテム選択イベントならば起動
			if(nCode == CN_COMMAND){
				MGCommandBase* pCmd = factory.CreateCommand(this, nID);
				if(pCmd){
					set_current_command_tool(pCmd);
				}
			}else if(nCode == CN_UPDATE_COMMAND_UI){
				// TODO: ファクトリーで UpdateCommandUI できたらやってみるのが望ましい。
				if(!CDocument::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)){
					// デフォルトのイベントルーティングではハンドルされなかったら、
					// 無条件にメニューをアクティブにする。
					CCmdUI* pCmdUI = static_cast<CCmdUI*>(pExtra);
					pCmdUI->Enable(factory.IsEnabled(this, nID));
				}
			}
			return TRUE; // TRUE はハンドルしたという意味。
		}else{
			MGCommandBase* pCmd = current_command_tool();
			bool bHandled = false;
			if(pCmd && pCmd->CanHandle(nID)){
				if(nCode == CN_COMMAND && pCmd->HandleMessage(nID)){
					return TRUE;
				}else if(nCode == CN_UPDATE_COMMAND_UI){
					// MFC 通常ルーティング
					if(CDocument::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)){
						return TRUE;
					}

					CCmdUI* pCmdUI = static_cast<CCmdUI*>(pExtra);
					// tool に流す
					pCmd->HandleUpdateUI(nID, pCmdUI);
				}
				return TRUE;
			}
		}
		// それ以外は
		// MFC 既定の処理に任せる。
	}
	// Call the base class version of OnCommand
	// so the message-map can handle the message.
	return CDocument::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
