//
// Asura_Wii_HomeButtonMenu.cpp
//
// Created by OF - 21 March 2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// Asura
#include "Core/Asura_Timers.h"
#include "Core/Asura_UserInput.h"
#include "FileAccess/Asura_FileAccess.h"
#include "Input/Asura_Rumble_System.h"
#include "Interface/Asura_CommandConsole.h"
#include "Rendering/Asura_Render.h"
#include "Sound/Asura_Music.h"
#include "Sound/Asura_Sound.h"
#include "Sound/Asura_StreamingBackgroundSound_System.h"

// Asura Wii
#include "Core/Asura_Wii_MEM2.h"
#include "Input/Asura_Wii_Input.h"
#include "HomeButton/Asura_Wii_HomeButtonMenu.h"
#include "Rendering/Asura_GX.h"
#include <string.h>

/*+------+------+------+------+------+------+------+------+------+------+*/

HBMControllerData	Asura_Wii_HomeButtonMenu::m_xHbmControllerData;
HBMDataInfo			Asura_Wii_HomeButtonMenu::m_xHbmDataInfo;

u_int				Asura_Wii_HomeButtonMenu::m_uState;

void*				Asura_Wii_HomeButtonMenu::m_pSoundFile;
void*				Asura_Wii_HomeButtonMenu::m_pSoundMemory;

OSTick				Asura_Wii_HomeButtonMenu::m_xBanIconTime;
u_int				Asura_Wii_HomeButtonMenu::m_uBanIconMode;

TPLPalettePtr		Asura_Wii_HomeButtonMenu::m_xIconTpl;

bool				Asura_Wii_HomeButtonMenu::s_bInitialised = false;
bool				Asura_Wii_HomeButtonMenu::s_bEnabled = true;

/*+------+------+------+------+------+------+------+------+------+------+*/

static int SoundCallback( int evt, int arg )
{
	//OSReport( "Sound Callback! %d, %d\n", evt, arg );
	return HBMSEV_RET_NONE;
}

/*+------+------+------+------+------+------+------+------+------+------+*/

//}	// Asura_Wii_HomeButtonMenu

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::Initialise()
{
	Asura_Assert(!s_bInitialised, "Already initialised");
	// Init all the relevant data for the home button menu.
	InitControllerData( &m_xHbmControllerData );
	InitHomeButtonInfo( &m_xHbmDataInfo );
	
	HBMCreate( &m_xHbmDataInfo );
	HBMSetAdjustFlag(1);

	InitialiseDisallowedIcon( &m_xIconTpl );

#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
	Asura_CommandConsole::AddCmd(L"Wii.AllowHomeButtonMenu", ConsoleCmd_Allow, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddCmd(L"Wii.EnableHomeButtonMenu", ConsoleCmd_Enable, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
#endif
	// Set up default states.
	m_uState		= eCS_HBM_INACTIVE;// | eCS_HBM_DISALLOWED;
	m_uBanIconMode	= eICON_OFF;
	s_bInitialised = true;
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::InitialiseSound()
{
	// Self explanatory?
	InitSound();
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::Shutdown()
{
	Asura_Assert(s_bInitialised, "Not initialised");
	// Shutdown all the home button data.
	ShutDownDisallowedIcon( m_xIconTpl );

	ShutDownSound();
	
	HBMDelete();

	ShutDownHomeButtonInfo( &m_xHbmDataInfo );

	s_bInitialised = false;
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::Activate()
{
	// Set the home button to an active state if it isn't already.
	if ( m_uState == eCS_HBM_INACTIVE )
	{
		// Pause all sound.
		Asura_Sound_System::PauseAllSystems();
		Asura_Rumble_System::PauseAllRumbling();

		Asura_Timers::SetSystemPause(true);
		HBMInit();
		m_uState	= eCS_HBM_FADING_IN;
	}
}

void Asura_Wii_HomeButtonMenu::Deactivate()
{
	Asura_Assert(m_uState != eCS_HBM_INACTIVE, "Already deactivated");
	m_uState = eCS_HBM_INACTIVE;
	// Unpause all sound.
	Asura_Sound_System::UnpauseAllSystems();
	Asura_Rumble_System::UnpauseAllRumbling();

	Asura_Timers::SetSystemPause(false);
}

/*+------+------+------+------+------+------+------+------+------+------+*/

bool Asura_Wii_HomeButtonMenu::IsActive()
{
	// Check if it is currently active.
	return ((m_uState & eCS_HBM_ALLOWEDMASK) != eCS_HBM_INACTIVE);
}

/*+------+------+------+------+------+------+------+------+------+------+*/

bool Asura_Wii_HomeButtonMenu::IsAllowed()
{
	// Is the menu currently allowed to come up?
	return !(m_uState & eCS_HBM_DISALLOWED);
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::Allow( bool bAllow )
{
	// Set the allowed state.
	if ( bAllow )
	{
		m_uState &= ~eCS_HBM_DISALLOWED;
		if (m_uBanIconMode	!= eICON_OFF)
		{
			m_uBanIconMode	= eICON_OFF;
		}
	}
	else
	{
		if(IsActive())
		{
			Deactivate();
			ActivateBanIcon();
		}
		m_uState |= eCS_HBM_DISALLOWED;
	}
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::ProcessController()
{
	if(!s_bEnabled) { return; }

	if ( m_uState == eCS_HBM_ACTIVE )
	{
		for( u_int uCount = 0; uCount < WPAD_MAX_CONTROLLERS; ++uCount )
		{
			// This is a good method for checking if a controller is plugged in or not.
			// With the new KPAD (ie SDK 2.4) you can no longer rely on the "dev_type"
			// field in KPADStatus.
			u_long	uType	= 0;
			long	sRet	= WPADProbe( (long)uCount, &uType );

			Asura_Wii_Controller* pxWiiController = static_cast<Asura_Wii_Controller*>(Asura_Input::GetController(uCount));
			KPADStatus* pxKpadStatus = pxWiiController->GetKpadStatus();

			if ( sRet != WPAD_ERR_NO_CONTROLLER )
			{
				// Need to enable the DPD if a controller has just been connected.
				if ( m_xHbmControllerData.wiiCon[uCount].use_devtype != WPAD_DEV_CORE || !WPADIsDpdEnabled( uCount ) )
				{
					KPADEnableDPD( uCount );
				}

				// Grab the viewing position.
				m_xHbmControllerData.wiiCon[uCount].kpad		= &pxKpadStatus[0];
				m_xHbmControllerData.wiiCon[uCount].pos.x		= pxKpadStatus[0].pos.x;
				m_xHbmControllerData.wiiCon[uCount].pos.y		= pxKpadStatus[0].pos.y;
				m_xHbmControllerData.wiiCon[uCount].use_devtype	= WPAD_DEV_CORE;
			}
			else
			{
				// Need to disable the DPD if we have just entered a "no controller" state.
				if ( m_xHbmControllerData.wiiCon[uCount].use_devtype != WPAD_DEV_NOT_FOUND )
				{
					KPADDisableDPD( uCount );
				}

				// Hide the pointer off screen when the controller is no longer plugged in.
				m_xHbmControllerData.wiiCon[uCount].kpad		= NULL;
				m_xHbmControllerData.wiiCon[uCount].pos.x		= -2.0f;
				m_xHbmControllerData.wiiCon[uCount].pos.y		= -2.0f;
				m_xHbmControllerData.wiiCon[uCount].use_devtype	= WPAD_DEV_NOT_FOUND;
			}
		}

		// What Buttons have been clicked on the menu?
		HBMSelectBtnNum xBtnSelect	= HBMCalc( &m_xHbmControllerData );
		switch( xBtnSelect )
		{
		case HBM_SELECT_HOMEBTN:
			// Close menu.
			m_uState	= eCS_HBM_FADING_OUT;

			// Need to de-initialise the menu.
			break;

		case HBM_SELECT_BTN1:
			// Handle return to Wii menu.
			PreShutdown();
			OSReturnToMenu();
			break;

		case HBM_SELECT_BTN2:
			// Handle Reset
			PreShutdown();
			OSRestart( 0 );
			break;

		case HBM_SELECT_BTN3:
			// Handle Manual displaying.
			// Not currently supported.
			break;

		case HBM_SELECT_BTN4:
			// Does nothing at present.
			break;
		};

	}
	else if ( (m_uState & eCS_HBM_ALLOWEDMASK) == eCS_HBM_INACTIVE )
	{
		// Check if the homebutton is pressed on any controllers.
		for( u_int uController = 0; uController < WPAD_MAX_CONTROLLERS; ++uController )
		{
			if(Asura_Input::IsKeyPressed(uController, ASURA_WII_INPUT_HOME))
			{
				// Check if the menu is currently allowed.
				if ( (m_uState & eCS_HBM_DISALLOWED) > 0 )
				{
					// It is not allowed.  Is the icon currently being shown?
					if ( m_uBanIconMode == eICON_OFF ) 
					{
						// Its not being shown.  Show it!
						ActivateBanIcon();
					}
				}
				else
				{
					// Menu is allowed.  Activate it.
					Activate();
				}
				break;
			}
		}

	}
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::Render()
{
	if(!s_bEnabled) { return; }

	// This code is lifted almost directly from the homebutton menu sample code.
	if ( m_uBanIconMode != eICON_OFF )
	{
		float fElapse = OSTicksToMilliseconds( OSDiffTick( OSGetTick(), m_xBanIconTime ) );

		u_char uBanIconAlpha;
		switch ( m_uBanIconMode )
		{
		case eICON_FADING_IN: /* AlphaIn(250ms) */
			uBanIconAlpha = ( u8 )( 255.9f * ( fElapse / 250.f ) );
			if ( fElapse >= 250.f )
			{
				m_xBanIconTime  = OSGetTick();
				m_uBanIconMode  = eICON_PAUSED;
				uBanIconAlpha = 255;
			}
			break;
		case eICON_PAUSED: /* Pause(1000ms) */
			if ( fElapse >= 1000.f )
			{
				m_xBanIconTime = OSGetTick();
				m_uBanIconMode = eICON_FADING_OUT;
			}
			uBanIconAlpha = 255;
			break;
		case eICON_FADING_OUT: /* AlphaOut(250ms) */
			uBanIconAlpha = ( u8 )( 255.9f * ( ( 250.f - fElapse ) / 250.f ) );
			if ( fElapse >= 250.f )
			{
				uBanIconAlpha	= 0;
				m_uBanIconMode	= eICON_OFF;
			}
			break;
		}

		DrawBanIcon( uBanIconAlpha );
	}
	if ( (m_uState & eCS_HBM_DISALLOWED) == 0 )
	{

		switch( m_uState )
		{
		case eCS_HBM_FADING_IN:
			// For now just Switch it to active state instantly.
			m_uState = eCS_HBM_ACTIVE;
			break;

		case eCS_HBM_FADING_OUT:
			// For now just Switch it to inactive state instantly.
			Deactivate();
			break;

		case eCS_HBM_ACTIVE:
			RenderMenu();
			break;
		};
	}
}

/*+------+------+------+------+------+------+------+------+------+------+*/
void Asura_Wii_HomeButtonMenu::ClearScreen()
{
	// Setup all the GX gumph.
	GXClearVtxDesc();

	GXSetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS,  GX_POS_XY,		GX_S16, 0 );
	GXSetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST,		GX_S16, 0 );
	GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
	GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );

	GXSetNumChans( 1 );
	GXSetChanCtrl( GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );

	GXSetNumTexGens( 1 );
	GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY );

	GXSetNumTevStages( 1 );
	GXSetTevColor( GX_TEVREG0, (GXColor){255, 255, 255, 255} );
	GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP_NULL, GX_COLOR_NULL );
	GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ONE );
	GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV );
	GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO );
	GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ADDHALF, GX_CS_SCALE_2, GX_TRUE, GX_TEVPREV );
	GXSetTevDirect(GX_TEVSTAGE0);

	GXSetBlendMode( GX_BM_BLEND, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR );
	GXSetZMode( GX_FALSE, GX_LEQUAL, GX_FALSE );

	GXSetCurrentMtx( GX_IDENTITY );

	const float fHalfWidth		= Asura_GX::GetScreenWidth() * .5f;
	const float fHalfHeight		= Asura_GX::GetScreenHeight() * .5f;

	GXSetViewport( 0.0f, 0.0f, fHalfWidth*2.0f, fHalfHeight*2.0f, 0.0f, 1.0f );
	GXSetScissor( 0, 0, fHalfWidth*2.0f, fHalfHeight*2.0f );

	Mtx44 xProjMtx;
	MTXOrtho( xProjMtx, fHalfHeight, -fHalfHeight, -fHalfWidth, fHalfWidth, 0.0f, 500.0f );
	GXSetProjection( xProjMtx, GX_ORTHOGRAPHIC );

	/* Rendering position can be anywhere in the safety frame */
	// Currently drawing in the bottom left corner.  This could easily be modified.
	GXBegin( GX_QUADS, GX_VTXFMT5, 4 );
	GXPosition2s16( fHalfWidth, -fHalfHeight);
	GXTexCoord2s16( 0, 1 );
	GXPosition2s16( fHalfWidth, fHalfHeight );
	GXTexCoord2s16( 0, 0 );
	GXPosition2s16( -fHalfWidth, fHalfHeight );
	GXTexCoord2s16( 1, 0 );
	GXPosition2s16( -fHalfWidth, -fHalfHeight);
	GXTexCoord2s16( 1, 1 );
	GXEnd();

	// Reset the current matrix.
	GXSetCurrentMtx( GX_PNMTX0 );

	Asura_GX::InitVertexFormats();



}
void Asura_Wii_HomeButtonMenu::RenderMenu()
{
	ClearScreen();

	// Set up the various bits of GX stuff that are required by the home button menu.
	GXClearVtxDesc();
	GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_TEX0,	GX_TEX_ST,		GX_F32,		0 );
	GXSetVtxAttrFmt( GX_VTXFMT4, GX_VA_POS,		GX_POS_XY,		GX_F32,		0 );
	GXSetVtxAttrFmt( GX_VTXFMT4, GX_VA_CLR0,	GX_CLR_RGB,		GX_RGB8,	0 );
	
    GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
    GXSetVtxDesc( GX_VA_CLR0, GX_DIRECT );

    GXSetNumChans( 1 );
    GXSetNumTexGens( 0 );
    GXSetNumTevStages( 1 );
    GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
    GXSetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
	GXSetTevDirect(GX_TEVSTAGE0);

    GXSetBlendMode( GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_CLEAR );
    GXSetZMode( GX_TRUE, GX_LEQUAL, GX_TRUE );
    GXSetCurrentMtx( GX_IDENTITY );

	const float fHalfWidth		= Asura_GX::GetScreenWidth() * .5f;
	const float fHalfHeight		= Asura_GX::GetScreenHeight() * .5f;

	GXSetViewport( 0.0f, 0.0f, fHalfWidth*2.0f, fHalfHeight*2.0f, 0.0f, 1.0f );
	GXSetScissor( 0, 0, fHalfWidth*2.0f, fHalfHeight*2.0f );

	Mtx44 xProjMtx;
	const bool bWidescreen = SCGetAspectRatio() ==  SC_ASPECT_RATIO_16x9;
	static float fHomeMenuWidth = bWidescreen ? 832.f : 608.0f;
	static float fHomeMenuHeight = 446;
	static float fHomeMenuOffsetX = 0.0f;
	static float fHomeMenuOffsetY = 0.0f;
	float fVertFudgeFactor = (528.0f / Asura_GX::GetScreenHeight());

	MTXOrtho(xProjMtx, (fHomeMenuOffsetY + fHomeMenuHeight/2.0f) * fVertFudgeFactor, (fHomeMenuOffsetY - fHomeMenuHeight/2.0f) * fVertFudgeFactor, fHomeMenuOffsetX - fHomeMenuWidth/2.0f, fHomeMenuOffsetX + fHomeMenuWidth/2.0f, 0.0f, 500.0f);

//	MTXOrtho( xProjMtx, fHalfHeight, -fHalfHeight, -fHalfWidth, fHalfWidth, 0.0f, 500.0f );
	GXSetProjection( xProjMtx, GX_ORTHOGRAPHIC );

	const Vec camPt = {0.0F, 0.0F, 800.0F};
	const Vec at = {0.0F, 0.0F, -100.0F};
	const Vec up = {0.0F, 1.0F, 0.0F};
	Mtx44 p;

	MTXLookAt(p, &camPt, &up, &at);
	GXLoadPosMtxImm(p, GX_PNMTX0);

	// Update sounds (A bit odd having it in a render function im aware).
	HBMUpdateSound();


	// Do the actual draw.
	HBMDraw();

	Asura_GX::InitVertexFormats();
}

DEBUGVAR short dbg_sBanIconSize = 56;
DEBUGVAR short dbg_sBanIconXPos = 0;
DEBUGVAR short dbg_sBanIconYPos = 0;

/*+------+------+------+------+------+------+------+------+------+------+*/
/* Render the "ban" icon */
void Asura_Wii_HomeButtonMenu::DrawBanIcon( u_char alpha )
{
	// Setup all the GX gumph.
    GXClearVtxDesc();
    
    GXSetVtxAttrFmt( GX_VTXFMT5, GX_VA_POS,  GX_POS_XY,		GX_S16, 0 );
    GXSetVtxAttrFmt( GX_VTXFMT5, GX_VA_TEX0, GX_TEX_ST,		GX_S16, 0 );
    GXSetVtxDesc( GX_VA_POS,  GX_DIRECT );
    GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );

    GXSetNumChans( 1 );
    GXSetChanCtrl( GX_COLOR0A0, GX_FALSE, GX_SRC_VTX, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE );
    
    GXSetNumTexGens( 1 );
    GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY );
    
    GXSetNumTevStages( 1 );
    GXSetTevColor( GX_TEVREG0, (GXColor){255, 255, 255, alpha} );
    GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL );
    GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC );
    GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV );
    GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_A0, GX_CA_TEXA, GX_CA_ZERO );
    GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV );
	GXSetTevDirect(GX_TEVSTAGE0);
    
    GXSetBlendMode( GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR );
    GXSetZMode( GX_FALSE, GX_LEQUAL, GX_FALSE );
    
    GXSetCurrentMtx( GX_IDENTITY );
    
	// Load the icon texture.
	GXTexObj xTexObj;
    TPLGetGXTexObjFromPalette( m_xIconTpl, &xTexObj, 0 );
    GXLoadTexObj( &xTexObj, GX_TEXMAP0 );
    
	const float fHalfWidth		= Asura_GX::GetScreenWidth() * .5f;
	const float fHalfHeight		= Asura_GX::GetScreenHeight() * .5f;

	GXSetViewport( 0.0f, 0.0f, fHalfWidth*2.0f, fHalfHeight*2.0f, 0.0f, 1.0f );
	GXSetScissor( 0, 0, fHalfWidth*2.0f, fHalfHeight*2.0f );

	Mtx44 xProjMtx;
	MTXOrtho( xProjMtx, fHalfHeight, -fHalfHeight, -fHalfWidth, fHalfWidth, 0.0f, 500.0f );
	GXSetProjection( xProjMtx, GX_ORTHOGRAPHIC );

	float fXScale = (fHalfWidth / fHalfHeight) * (480.0f / 640.0f) * (SCGetAspectRatio() ==  SC_ASPECT_RATIO_16x9 ? 3.0f / 4.0f : 1.0f);

	const short sHalfIconSize = dbg_sBanIconSize / 2;
    /* Rendering position can be anywhere in the safety frame */
    GXBegin( GX_QUADS, GX_VTXFMT5, 4 );
    GXPosition2s16( dbg_sBanIconXPos + sHalfIconSize * fXScale, dbg_sBanIconYPos - sHalfIconSize);
    GXTexCoord2s16( 1, 1 );
    GXPosition2s16( dbg_sBanIconXPos + sHalfIconSize * fXScale, dbg_sBanIconYPos + sHalfIconSize );
    GXTexCoord2s16( 1, 0 );
    GXPosition2s16( dbg_sBanIconXPos - sHalfIconSize * fXScale, dbg_sBanIconYPos + sHalfIconSize );
    GXTexCoord2s16( 0, 0 );
    GXPosition2s16( dbg_sBanIconXPos - sHalfIconSize * fXScale, dbg_sBanIconYPos - sHalfIconSize);
    GXTexCoord2s16( 0, 1 );
    GXEnd();

	// Reset the current matrix.
	GXSetCurrentMtx( GX_PNMTX0 );

	Asura_GX::InitVertexFormats();
	Asura_Render::CurrentStates.RequestTextureIndex(0, ASURA_TEXTURE_NONE);
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::PreShutdown()
{
	// Black the screen out ready for a reset or return to wii menu.
	VISetBlack( TRUE );
	VIFlush();
	VIWaitForRetrace();
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::InitControllerData( HBMControllerData* pxHbmControllerData )
{
	// Setup the default controller data.
	u_int uCount	= 0;
	while( uCount < WPAD_MAX_CONTROLLERS )
	{
		pxHbmControllerData->wiiCon[uCount].kpad		= NULL;
		pxHbmControllerData->wiiCon[uCount].pos.x		= 0.f;
		pxHbmControllerData->wiiCon[uCount].pos.y		= 0.f;
		pxHbmControllerData->wiiCon[uCount].use_devtype = WPAD_DEV_CORE;

		uCount++;
	}
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::InitHomeButtonInfo( HBMDataInfo* pxHbmInfo )
{
	// This function is adapted from the home button example code.
	char nameBuf[128];

    /* Switch based on the lanugage settings */
    pxHbmInfo->region = SCGetLanguage();
    switch (pxHbmInfo->region)
    {
    case SC_LANG_JAPANESE:
        strcpy( nameBuf, "HomeButton/homeBtn.arc" );
        break;
    case SC_LANG_ENGLISH:
        strcpy( nameBuf, "HomeButton/homeBtn_ENG.arc" );
        break;
    case SC_LANG_GERMAN:
        strcpy( nameBuf, "HomeButton/homeBtn_GER.arc" );
        break;
    case SC_LANG_FRENCH:
        strcpy( nameBuf, "HomeButton/homeBtn_FRA.arc" );
        break;
    case SC_LANG_SPANISH:
        strcpy( nameBuf, "HomeButton/homeBtn_SPA.arc" );
        break;
    case SC_LANG_ITALIAN:
        strcpy( nameBuf, "HomeButton/homeBtn_ITA.arc" );
        break;
    case SC_LANG_DUTCH:
        strcpy( nameBuf, "HomeButton/homeBtn_NED.arc" );
        break;
    default:
        pxHbmInfo->region=SC_LANG_ENGLISH;
        strcpy( nameBuf, "HomeButton/homeBtn_ENG.arc" );
        break;
    }

	u_int uFileSize	= 0;
    pxHbmInfo->layoutBuf	= OpenAllocAndReadFileHelper( nameBuf,						&uFileSize );
	pxHbmInfo->spkSeBuf		= OpenAllocAndReadFileHelper( "HomeButton/SpeakerSe.arc",	&uFileSize );
	pxHbmInfo->msgBuf		= OpenAllocAndReadFileHelper( "HomeButton/home.csv",		&uFileSize );
	pxHbmInfo->configBuf	= OpenAllocAndReadFileHelper( "HomeButton/config.txt",		&uFileSize );
	pxHbmInfo->configBufSize = uFileSize;

    pxHbmInfo->sound_callback	= SoundCallback;
    pxHbmInfo->backFlag			= 0;
    pxHbmInfo->cursor			= 0;

	const bool bWidescreen = SCGetAspectRatio() ==  SC_ASPECT_RATIO_16x9;
	pxHbmInfo->adjust.x			= bWidescreen ? 832.f / 608.f : 1.f;
    pxHbmInfo->adjust.y			= 1.0f;
	
	const bool b25Fps = VIGetTvFormat() == VI_PAL;
	pxHbmInfo->frameDelta		= b25Fps ? 2.4f : 2.0f;
    
	pxHbmInfo->mem			= ASURA_WII_MEM2_ALLOC( HBM_MEM_SIZE );
	pxHbmInfo->memSize		= HBM_MEM_SIZE;
	pxHbmInfo->pAllocator	= NULL;
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::ShutDownHomeButtonInfo( HBMDataInfo* pxHbmInfo )
{
	// Free all the data.
	Asura_Wii_MEM2::Free( pxHbmInfo->layoutBuf	);
	Asura_Wii_MEM2::Free( pxHbmInfo->spkSeBuf	);
	Asura_Wii_MEM2::Free( pxHbmInfo->msgBuf		);
	Asura_Wii_MEM2::Free( pxHbmInfo->configBuf	);

	Asura_Wii_MEM2::Free( pxHbmInfo->mem		);
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::InitSound()
{
	u_int uFileSize	= 0;

	// Load the file.
	m_pSoundFile	= OpenAllocAndReadFileHelper( "homeButton/HomeButtonSe.arc", &uFileSize );
	// Attempt to load sound file.
	m_pSoundMemory	= ASURA_WII_MEM2_ALLOC( HBM_MEM2_SIZE_MEMORY );

	// Let the home button menu do what it wants with the data.
	HBMCreateSound( m_pSoundFile, m_pSoundMemory, HBM_MEM2_SIZE_MEMORY );
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::ShutDownSound()
{
	// Free sound data.
    Asura_Wii_MEM2::Free( m_pSoundMemory );
	Asura_Wii_MEM2::Free( m_pSoundFile );
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::InitialiseDisallowedIcon( TPLPalettePtr* pxIcon )
{
	// Load up the home menu disallowed icon texture.
	u_int uFileSize	= 0;
	*pxIcon = ( TPLPalettePtr )OpenAllocAndReadFileHelper( "HomeButton/homeBtnIcon.tpl", &uFileSize );
	TPLBind( *pxIcon );
}

/*+------+------+------+------+------+------+------+------+------+------+*/

void Asura_Wii_HomeButtonMenu::ShutDownDisallowedIcon( TPLPalettePtr xIcon )
{
	// Free the texture.
	Asura_Wii_MEM2::Free( xIcon );
}

void Asura_Wii_HomeButtonMenu::ActivateBanIcon()
{
	m_uBanIconMode	= eICON_FADING_IN;
	m_xBanIconTime	= OSGetTick();
}

/*+------+------+------+------+------+------+------+------+------+------+*/

u_char*	Asura_Wii_HomeButtonMenu::OpenAllocAndReadFileHelper( const char* pszFilename, u_int* puFileSize )
{
	// This is a simple helper function which aids in the loading of all the data above.  
	if ( Asura_FileAccess::FileExists(pszFilename) )
	{
		// Read File
		Asura_Handle iFileHandle = Asura_FileAccess::Open( pszFilename );
		if ( iFileHandle != ASURA_INVALID_HANDLE )	// Did file open?
		{
			*puFileSize	= Asura_FileAccess::GetFileSize( iFileHandle );

			u_char* puData = (u_char*)ASURA_WII_MEM2_ALLOC( *puFileSize );

			if ( !Asura_FileAccess::ReadData( iFileHandle, puData, *puFileSize ) )
			{
				Asura_Wii_MEM2::Free( puData );
			}

			Asura_FileAccess::Close( iFileHandle );

			return puData;
		}
	}
	return NULL;
}

/*+------+------+------+------+------+------+------+------+------+------+*/

#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
bool Asura_Wii_HomeButtonMenu::ConsoleCmd_Allow(bool bAllow, bool bHelp, bool bInterrogate)
{
	if(bHelp || bInterrogate)
	{
		Asura_CommandConsole::Printf("Sets whether the home button menu is allowed");
	}
	else
	{
		Allow(bAllow);
	}
	return true;
}

bool Asura_Wii_HomeButtonMenu::ConsoleCmd_Enable(bool bEnable, bool bHelp, bool bInterrogate)
{
	if(bHelp || bInterrogate)
	{
		Asura_CommandConsole::Printf("Sets whether the home button menu is enabled");
	}
	else
	{
		SetEnabled(bEnable);
	}
	return true;
}
#endif

void Asura_Wii_HomeButtonMenu::SetEnabled(bool bEnabled)
{
	if(!bEnabled)
	{
		// Ensure everything's turned off.
		m_uState		= eCS_HBM_INACTIVE;
		m_uBanIconMode	= eICON_OFF;
	}
	s_bEnabled = bEnabled;
}
