/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/utils/menusystem/menu_handler.cpp

*/

#include "sgx/core/core.hpp"
#include "utils/menusystem/menusystem.hpp"

CGameMenuHandler::CGameMenuHandlerSettings::CGameMenuHandlerSettings() {

}


tBOOL
CGameMenuHandler::onGUIWidgetSelectActive(const sgxWidget *pWidget) {
	tUINT32 ud = pWidget->getUserData();

	if (ud == (tUINT32)-1) {
		changeMenu(popMenuStack());
	} else if (isMenu()) {
		m_pCurrentMenu->onGameMenuOptionSelect(this, ud);
	} else {
		m_pCurrentAlert->onGameAlertOptionSelect(this, ud);
		delete m_pCurrentAlert;
		m_pCurrentAlert = NULL;
	}
	return TRUE;
}

CGameMenuHandler::CGameMenuHandler(const CGameMenuHandlerSettings &settings) :
	m_bIsMenu(TRUE),
	m_pCurrentAlert(NULL),
	m_pCurrentMenu(NULL),
	m_pOldGUIRoot(NULL),
	m_Settings(settings),
	m_State(CGameMenuHandler::eNull)
{

	m_pFrame = CSGXGUI::get()->createFrame();

	tINT32 defaultWidth = CSGXGUI::get()->getCurrentSkin()->getDefaultButtonWidth();
	for(int i=0;i<MAX_MENU_BUTTONS;++i) {
		m_pButtons[i] = m_pFrame->addChildWidget(CSGXGUI::get()->createButton(0,0,sgxGUIButtonParams("", defaultWidth), NULL, i));
		m_pButtons[i]->setHandler(this);
	}

	m_pBackButton = m_pFrame->addChildWidget(CSGXGUI::get()->createImageButton(32,320,sgxGUIImageButtonParams(sgxGUISkinnedImageButton::eLeft), NULL, (tUINT32)-1));
	m_pBackButton->setHandler(this);
}

CGameMenuHandler::~CGameMenuHandler() {
}

void CGameMenuHandler::openMenu() {
	//
	m_pOldGUIRoot = CSGXGUI::get()->setRootWidget(m_pFrame);
}

void CGameMenuHandler::closeMenu() {
	clearMenuStack();
	m_pCurrentAlert = NULL;
	m_pCurrentMenu = NULL;
	m_State = eNull;
	CSGXGUI::get()->setRootWidget(m_pOldGUIRoot);
	m_pOldGUIRoot = NULL;
}

tBOOL CGameMenuHandler::isMenuOpen() const {
	return m_pCurrentMenu ? TRUE : FALSE;
}

tBOOL CGameMenuHandler::isMenu() {
	return m_bIsMenu;
}

CGameMenuHandler::tMenuType CGameMenuHandler::getMenuType() {
	return m_MenuType;
}

CGameMenuHandler::tAlertType CGameMenuHandler::getAlertType() {
	return m_AlertType;
}


void 
CGameMenuHandler::prepareAlert(const sgxString &msg, const sgxString &question, tAlertType alert) {
	m_Message = msg;
	m_Question = question;
	m_bIsMenu = FALSE;
	m_AlertType = alert;
	
	for(int i=0;i<MAX_MENU_BUTTONS;++i) {
		m_pButtons[i]->hide();
	}
	m_pBackButton->hide();

	sgxPoint2i pos;
	switch(alert) {
		case eYesNo:
		case eOkCancel:
				m_pButtons[0]->show();
				m_pCurrentAlert->onGameAlertGetWidgetPosition(this, pos, 0, 2, m_pButtons[0]);
				m_pButtons[0]->setPosition(pos.x, pos.y);
				m_pButtons[1]->show();
				m_pCurrentAlert->onGameAlertGetWidgetPosition(this, pos, 1, 2, m_pButtons[1]);
				m_pButtons[1]->setPosition(pos.x, pos.y);
				break;
		case eOk:
		case eYes:
		case eCancel:
				m_pButtons[0]->show();
				m_pCurrentAlert->onGameAlertGetWidgetPosition(this, pos, 0, 1, m_pButtons[0]);
				m_pButtons[0]->setPosition(pos.x, pos.y);
				break;
	}
	//
	switch(alert) {
		case eYesNo:
			m_pButtons[1]->setText(SGXText::getText("No"));
		case eYes:
			m_pButtons[0]->setText(SGXText::getText("Yes"));
			break;
		case eOkCancel:
			m_pButtons[1]->setText(SGXText::getText("Cancel"));
		case eOk:
			m_pButtons[0]->setText(SGXText::getText("OK"));
			break;
		case eCancel:
			m_pButtons[0]->setText(SGXText::getText("Cancel"));
			break;
	}
}

void 
CGameMenuHandler::prepareMenu(const sgxString &msg, const CButtonInfo *buttonList, tMenuType type) {
	m_Message = msg;
	m_bIsMenu = TRUE;
	m_MenuType = type;
	
	for(int i=0;i<MAX_MENU_BUTTONS;++i) {
		m_pButtons[i]->hide();
	}

	sgxPoint2i pos;
	for(int i=0;i<MAX_MENU_BUTTONS && buttonList[i].pText;++i) {
		m_pCurrentMenu->onGameMenuGetWidgetPosition(this, pos, i, m_pButtons[i]);

		m_pButtons[i]->setText(buttonList[i].pText);
		m_pButtons[i]->setUserData(buttonList[i].userdata);
		m_pButtons[i]->setPosition(pos.x, pos.y);
		m_pButtons[i]->show();
	}
}

void 
CGameMenuHandler::prepareMenu(const sgxString &msg, const char *buttonList[], tMenuType type) {
	m_Message = msg;
	m_bIsMenu = TRUE;
	m_MenuType = type;
	
	for(int i=0;i<MAX_MENU_BUTTONS;++i) {
		m_pButtons[i]->hide();
	}

	sgxPoint2i pos;
	for(int i=0;i<MAX_MENU_BUTTONS && buttonList[i];++i) {
		m_pCurrentMenu->onGameMenuGetWidgetPosition(this, pos, i, m_pButtons[i]);

		m_pButtons[i]->setText(buttonList[i]);
		m_pButtons[i]->setPosition(pos.x, pos.y);
		m_pButtons[i]->show();
	}
}

void 
CGameMenuHandler::prepareMenu(const sgxString &msg, const sgxVector<sgxString> &buttonList, tMenuType type) {
	m_Message = msg;
	m_bIsMenu = TRUE;
	m_MenuType = type;

	int num = buttonList.size();
	sgxPoint2i pos;
	for(int i=0;i<MAX_MENU_BUTTONS;++i) {
		if (i < num) {
			m_pCurrentMenu->onGameMenuGetWidgetPosition(this, pos, i, m_pButtons[i]);

			m_pButtons[i]->setText(buttonList[i]);
			m_pButtons[i]->setPosition(pos.x, pos.y);
			m_pButtons[i]->show();

		} else {
			m_pButtons[i]->hide();
		}
	}
}

sgxWidget *CGameMenuHandler::getButtonWidget(const tUINT32 index) {
	if (index >= MAX_MENU_BUTTONS) {
		return NULL;
	}
	return m_pButtons[index];
}

void CGameMenuHandler::clearMenuStack() {
	while(!m_MenuStack.empty()) {
		m_MenuStack.pop();
	}
}

void CGameMenuHandler::pushMenuStack(CSGXMenu *pMenu) {
	m_MenuStack.push(pMenu);
}

CSGXMenu *CGameMenuHandler::popMenuStack() {
	CSGXMenu *pMenu = m_MenuStack.top();
	m_MenuStack.pop();
	return pMenu;
}



void CGameMenuHandler::changeMenu(CSGXMenu *pMenu) {
	
	if (m_pCurrentAlert) {	// if we were presenting an alert, we can avoid the menu exit
		m_State = eNull;
		m_pCurrentMenu->endExit(this);
	}


	if (!m_pCurrentMenu) {
		// this is the first menu being opened, so store
		// the current root widget
		openMenu();
	}

	if (m_State == eProcess) {
		m_State = eExit;
		m_pNewMenu = pMenu;
		m_pBackButton->hide();
		pushMenuStack(m_pCurrentMenu);
		m_pCurrentMenu->beginExit(this);
	} else if (m_State == eNull) {
		m_pCurrentMenu = pMenu;
		m_State = eEnter;
		m_pBackButton->hide();
		m_pCurrentMenu->beginEntrance(this);
	}
}


void CGameMenuHandler::openAlert(CSGXAlert *pAlert) {

	m_pCurrentAlert = pAlert;
	m_pCurrentAlert->onGameAlertPrepareAlert(this);

}

void 
CGameMenuHandler::draw() const {
	if (!isMenuOpen()) {
		return;
	} 
	
	CSGXGUI::get()->drawScreens(m_pOldGUIRoot);

	if (m_pCurrentAlert) {
		m_pCurrentAlert->onGameAlertDrawAlert(this);
	} else if (m_pCurrentMenu) {
		m_pCurrentMenu->onGameMenuDrawMenu(this);
	}
}

void CGameMenuHandler::updateMenu(const tREAL32 telaps) {

	m_pCurrentMenu->onGameMenuUpdate(this, telaps);

	switch(m_State) {
		case eEnter:
			if (m_pCurrentMenu->updateEntrance(this, telaps)) {
					m_pCurrentMenu->endEntrance(this);
					//
					if (m_MenuType == eMainMenu) {
						m_pBackButton->hide();
					} else {
						m_pBackButton->show();
					}
					//
					m_State = eProcess;
				}
		break;
		case eProcess:
 			m_pCurrentMenu->updateActive(this, telaps);
		break;
		case eExit:
			if (m_pCurrentMenu->updateExit(this, telaps)) {
				m_pCurrentMenu->endExit(this);

				m_State = eEnter;
				m_pNewMenu->beginEntrance(this);
				m_pCurrentMenu = m_pNewMenu;
			}
		break;
	}
}

void CGameMenuHandler::updateAlert(const tREAL32 telaps) {
SGX_UNUSED(telaps);
	if (m_pCurrentAlert) {
		m_pCurrentAlert->onGameAlertUpdateAlert(this, telaps);
	}
}

void CGameMenuHandler::update(const tREAL32 telaps) {
	if (!isMenuOpen()) {
		// NULL
	} else if (m_pCurrentAlert) {
		updateAlert(telaps);
	} else {
		updateMenu(telaps);
	}
}

