/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/* ***************************************************** */
/********************************************************************/
/**
 * @file CommandStateOwner.cpp:
 * @brief CommandStateOwner.h の実装
 */
#include "stdafx.h"
#include "Common/CommandStateOwner.h"

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

// static領域にあるオブジェクトのためのコンストラクタ
MGCommandStateOwner::MGCommandStateOwner(fugenDoc* pDoc)
 :MGCommandBase(pDoc,0),m_state(0),m_next(0){
}

// 継承用コンストラクタ
MGCommandStateOwner::MGCommandStateOwner(fugenDoc* pDoc, UINT nID)
 :MGCommandBase(pDoc,nID),m_state(0),m_next(0){
}

MGCommandStateOwner::~MGCommandStateOwner(){
	delete m_next;
	delete m_state;
}

//Clear the current command state.
//This will cause the termination of this command.
void MGCommandStateOwner::clear_state(){
	delete m_next;
	m_next=0;
	if(!m_state) return;
	m_state->terminate_tool();
	delete m_state;
	m_state=0;
}

// 次のステップに移行するときに呼ばれる関数
void MGCommandStateOwner::ChangeState(
){
	if(!m_next) return;
	MGCommandBase* next=m_next;
	m_next=0;
	set_child_current_command(next);
}

bool MGCommandStateOwner::OnKeyDown(fugenView* window, UINT nChar,UINT nRepCnt, UINT nFlags){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnKeyDown(window, nChar, nRepCnt, nFlags)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnKeyUp(fugenView* window, UINT nChar, UINT nRepCnt, UINT nFlags){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnKeyUp(window, nChar, nRepCnt, nFlags)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnLButtonDblClk(fugenView* window,UINT nFlags, CPoint point){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnLButtonDblClk(window, nFlags, point)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnLButtonDown(fugenView* window,UINT nFlags, CPoint point){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnLButtonDown(window, nFlags, point)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnLButtonUp(fugenView* window, CPoint old_point, UINT nFlags, CPoint point){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnLButtonUp(window, old_point, nFlags, point)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnMouseMove(fugenView* window,UINT nFlags, CPoint point){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnMouseMove(window, nFlags, point)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnMouseWheel(fugenView* window,UINT nFlags, short zDelta, CPoint pt){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnMouseWheel(window, nFlags, zDelta, pt)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnRButtonDblClk(fugenView* window,UINT nFlags, CPoint point){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnRButtonDblClk(window, nFlags, point)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnRButtonDown(fugenView* window,UINT nFlags, CPoint point){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnRButtonDown(window, nFlags, point)) return true;
	ChangeState();
	return false;
}

bool MGCommandStateOwner::OnRButtonUp(
	fugenView* window,CPoint old_point,UINT nFlags, CPoint point
){
	MGCommandBase* current=GetCurState();
	if(!current) return true;
	if(current->OnRButtonUp(window, old_point, nFlags, point)) return true;
	ChangeState();
	return false;
}


bool MGCommandStateOwner::OnSetCursor(
	fugenView* pView,
	CWnd* pWnd,
	UINT nHitTest,
	UINT message)
{
	MGCommandBase* current = GetCurState();
	if(!current){
		// 基底クラスの振る舞いに合わせる。
		// おそらく何もしない。
		return MGCommandBase::OnSetCursor(pView, pWnd, nHitTest, message);
	}

	// 現在の子 state にカーソル変更の機会を与える。
	return current->OnSetCursor(pView, pWnd, nHitTest, message);
}

bool MGCommandStateOwner::initiate_tool(){
	MGCommandBase::initiate_tool();
	return false;
}

//Set the next state command.
void MGCommandStateOwner::set_child_current_command(
	MGCommandBase* currentState
){
	ASSERT(!m_next);
	if(m_state){
		m_state->terminate_tool();
		delete m_state;
	}
	m_state = currentState;
	m_state->set_owner_command(this);
	if(currentState->initiate_tool()) clear_state();
}

//Set the next state command.
void MGCommandStateOwner::set_child_next_command(
	MGCommandBase* nextState
){
	ASSERT(!m_next);
	m_next = nextState;
}

bool MGCommandStateOwner::terminate_tool(bool cancel){
	clear_state();
	MGCommandBase::terminate_tool(cancel);
	return true;
}

//update snap mode for locate.
void MGCommandStateOwner::updateSnapMode(const MGSnapAttrib& sattrib){
	if(m_state)
		m_state->updateSnapMode(sattrib);
}

void MGCommandStateOwner::ModifyContextMenu(CMenu& popup){
	if(m_state){
		m_state->ModifyContextMenu(popup);
	}
}

bool MGCommandStateOwner::CanHandle(UINT nID) const{
	if(MGCommandBase::CanHandle(nID)){
		return true;
	}

	if(m_state){
		return m_state->CanHandle(nID);
	}
	return false;
}

bool MGCommandStateOwner::HandleMessage(UINT nID){
	if(MGCommandBase::HandleMessage(nID)){
		return true;
	}

	if(m_state){
		return m_state->HandleMessage(nID);
	}
	return false;
}

bool MGCommandStateOwner::HandleUpdateUI(UINT nID, CCmdUI* pCmdUI){
	if(MGCommandBase::HandleUpdateUI(nID, pCmdUI)){
		return true;
	}

	if(m_state){
		return m_state->HandleUpdateUI(nID, pCmdUI);
	}
	return false;
}
