
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_PSP_SCEUtility_FileListHandler.cpp
// Author : Andy Tate
// Date   : 5-Oct-2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "PSPEmul/SCEUtility/Asura_PSP_SCEUtility_FileListHandler.h"

// Asura independent header-files...
#include "Core/Asura_Maths.h"
#include "Core/Asura_String.h"
#include "Core/Asura_UserInput.h"
#include "Rendering/Asura_Font_System.h"

// Asura platform header-files...

// Game independent header-files...

// Game platform header-files...


////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////

// Maximum number of characters in various strings...
const u_int						g_uFileListMaxFilenameLength		= 256;
const u_int						g_uFileListMaxSlotSizeTextLength	= 256;

// Maximum number of slots visible...
const u_int						g_uFileListMaxVisibleSlots	= 13;

// Positional data to be used for this screen...
static const Asura_IntVector_2	g_xFileListTitlePosition (240, 16);

static const Asura_IntVector_2	g_xFileListMessagePosition (240, 136);

static const Asura_IntVector_2	g_xFileListFirstSlotPosition (32, 48);
static const Asura_IntVector_2	g_xFileListSlotIncrement (0, 16);

static const Asura_IntVector_2	g_xFileListEmptySlotPosition (240, 136);
static const Asura_IntVector_2	g_xFileListCurrentSlotTitlePosition (240, 136);
static const Asura_IntVector_2	g_xFileListCurrentSlotSizePosition (240, 168);
static const Asura_IntVector_2	g_xFileListCurrentSlotDateAndTimePosition (240, 184);
static const Asura_IntVector_2	g_xFileListCurrentSlotDescriptionPosition (240, 200);


////////////////////////////////////////////////////////////////////////////////
// Static variable declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Private functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::DeleteList
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Deletes the currently allocated file-list.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::DeleteList (void)
{
	// Delete the data...
	for (int s = 0; s < m_iNumSlots; s++)
	{
		delete	(m_ppxFileData [s]);
	}

	delete []	(m_ppxFileData);

	// Reset the slot variables...
	m_iNumSlots		= 0;
	m_iCurrentSlot	= 0;
	m_ppxFileData	= NULL;
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::DeleteList'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::RefreshList
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Refreshes the file-list to be displayed.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::RefreshList (void)
{
	int	iCurrentSlot	= 0;

	// Remove any existing data...
	DeleteList	();

	// Allocate the slot-list...
	m_ppxFileData	= new Asura_PSP_SCEUtility_FileData* [m_iMaxSlots];

	// Create the filenames...
	for (int s = 0; s < m_iMaxSlots; s++)
	{
		char	szFilename [g_uFileListMaxFilenameLength + 1];

		// Create the filename...
		Asura_PrintfToBfr	(szFilename, "PSP_Saves\\%04d\\DATA.BIN", g_uFileListMaxFilenameLength, true, s);

		// Allocate this slot...
		m_ppxFileData [s]	= new Asura_PSP_SCEUtility_FileData (szFilename);
	}

	// Read the header of each file (if possible)...
	for (int s = 0; s < m_iMaxSlots; s++)
	{
		// Can we read the header-data for this file?
		if (m_ppxFileData [s]->ReadHeaderData() || m_bDisplayEmpty)
		{
			// Yes - increase the slot count...
			m_iNumSlots++;
		}

		else
		{
			// No - delete the data and reset the pointer...
			delete	(m_ppxFileData [s]);

			m_ppxFileData [s]	= NULL;
		}
	}

	// Update the slot list...
	for (int s = 0; s < m_iMaxSlots; s++)
	{
		// Do we have data in this slot?
		if (NULL != m_ppxFileData [s])
		{
			// Yes - copy the data into the slot data...
			m_ppxFileData [iCurrentSlot++]	= m_ppxFileData [s];
		}
	}

	Asura_Assert	((m_iNumSlots == iCurrentSlot), "Mismatch in number of slots used.");
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::RefreshList'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::RenderTitle
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Renders the title for this file-list.
//
// Parameters   : The screen-scale to use when calculating positions.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::RenderTitle (const float fScreenScale) const
{
	Asura_Vector_2	xPosition;

	// Yes - calculate the current slot-data positions...
	CalculateScreenPosition	(fScreenScale, g_xFileListTitlePosition, xPosition);

	// Display the current slot's title...
	Asura_Font_System::PrintLongString
	(
		m_wszTitle,
		NULL,
		xPosition [0],
		xPosition [1],
		1.0f,
		fScreenScale,
		0xFFFFFFFF,
		ASURA_TEXTFORMAT_CENTREJUSTIFIED
	);
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::RenderTitle'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::RenderNoSlotsMessage
// Author       : Andy Tate
// Date         : 6-Oct-2005
//
// Description  : Renders the no slots message for this file-list.
//
// Parameters   : The screen-scale to use when calculating positions.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::RenderNoSlotsMessage (const float fScreenScale) const
{
	Asura_Vector_2	xPosition;

	// Yes - calculate the current slot-data positions...
	CalculateScreenPosition	(fScreenScale, g_xFileListMessagePosition, xPosition);

	// Display the current slot's title...
	Asura_Font_System::PrintLongString
	(
		L"No data to access",
		NULL,
		xPosition [0],
		xPosition [1],
		1.0f,
		fScreenScale,
		0xFFFFFFFF,
		ASURA_TEXTFORMAT_CENTREJUSTIFIED
	);
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::RenderNoSlotsMessage'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::RenderSlot
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Renders the data for this slot.
//
// Parameters   : A reference to the current slot data and the screen-scale to
//				  use when calculating positions.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::RenderSlot (const float fScreenScale,
													   const Asura_PSP_SCEUtility_FileData& xFileData) const
{
	char			szSizeText [g_uFileListMaxSlotSizeTextLength];

	Asura_Vector_2	xTitlePosition;
	Asura_Vector_2	xSizePosition;
	Asura_Vector_2	xDateAndTimePosition;
	Asura_Vector_2	xDescriptionPosition;

	// Create the size text...
	Asura_PrintfToBfr	(szSizeText, "%d bytes", g_uFileListMaxSlotSizeTextLength, true, xFileData.GetDataSize());

	// Calculate the current slot-data positions...
	CalculateScreenPosition	(fScreenScale, g_xFileListCurrentSlotTitlePosition, xTitlePosition);
	CalculateScreenPosition	(fScreenScale, g_xFileListCurrentSlotSizePosition, xSizePosition);
	CalculateScreenPosition	(fScreenScale, g_xFileListCurrentSlotDateAndTimePosition, xDateAndTimePosition);
	CalculateScreenPosition	(fScreenScale, g_xFileListCurrentSlotDescriptionPosition, xDescriptionPosition);

	// Display the current slot's title...
	Asura_Font_System::PrintLongString
	(
		xFileData.GetTitle(),
		NULL,
		xTitlePosition [0],
		xTitlePosition [1],
		1.0f,
		fScreenScale,
		0xFFFFFFFF,
		ASURA_TEXTFORMAT_LEFTJUSTIFIED
	);

	// Display the current slot's size...
	Asura_Font_System::PrintShortString
	(
		szSizeText,
		NULL,
		xSizePosition [0],
		xSizePosition [1],
		1.0f,
		0.5f *fScreenScale,
		0xFFFFFFFF,
		ASURA_TEXTFORMAT_LEFTJUSTIFIED
	);

	// Display the current slot's title...
	Asura_Font_System::PrintShortString
	(
		xFileData.GetDataAndTimeString(),
		NULL,
		xDateAndTimePosition [0],
		xDateAndTimePosition [1],
		1.0f,
		0.5f * fScreenScale,
		0xFFFFFFFF,
		ASURA_TEXTFORMAT_LEFTJUSTIFIED
	);

	// Display the current slot's description...
	Asura_Font_System::PrintLongString
	(
		xFileData.GetDescription(),
		NULL,
		xDescriptionPosition [0],
		xDescriptionPosition [1],
		1.0f,
		0.5f * fScreenScale,
		0xFFFFFFFF,
		ASURA_TEXTFORMAT_LEFTJUSTIFIED
	);
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::RenderSlot'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::RenderEmptySlot
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Renders the data for this empty slot.
//
// Parameters   : A reference to the current slot data and the screen-scale to
//				  use when calculating positions.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::RenderEmptySlot (const float fScreenScale,
															const Asura_PSP_SCEUtility_FileData& xFileData) const
{
	Asura_Vector_2	xPosition;

	// Calculate the current slot-data positions...
	CalculateScreenPosition	(fScreenScale, g_xFileListEmptySlotPosition, xPosition);

	// Display the current slot's title...
	Asura_Font_System::PrintLongString
	(
		L"Empty Slot",
		NULL,
		xPosition [0],
		xPosition [1],
		1.0f,
		fScreenScale,
		0xFF808080,
		ASURA_TEXTFORMAT_LEFTJUSTIFIED
	);
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::RenderEmptySlot'. ///



////////////////////////////////////////////////////////////////////////////////
// Protected functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Public functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::Asura_PSP_SCEUtility_FileListHandler
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Constructor for the PSP Utility file-list handler.
//
// Parameters   : 
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_PSP_SCEUtility_FileListHandler::Asura_PSP_SCEUtility_FileListHandler (const Asura_UnicodeChar* wszTitle,
																			const int iMaxSlots,
																			const bool bDisplayEmpty) :
	m_wszTitle(wszTitle),
	m_bDisplayEmpty(bDisplayEmpty),
	m_iMaxSlots(iMaxSlots),
	m_iNumSlots(0),
	m_iCurrentSlot(0),
	m_ppxFileData(NULL)
{
	// Refresh the list...
	RefreshList	();
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::Asura_PSP_SCEUtility_FileListHandler'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::~Asura_PSP_SCEUtility_FileListHandler
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Constructor for the PSP Utility file-list handler.
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_PSP_SCEUtility_FileListHandler::~Asura_PSP_SCEUtility_FileListHandler ()
{
	// Delete any previously allocated list...
	DeleteList	();
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::~Asura_PSP_SCEUtility_FileListHandler'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::Update
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Handles the update of the SCE Utility file-list.
//
// Parameters   : Reference to the cancelled flag to be filled in.
//
// Return value : "true" if still updating, "false" if we're finished.
////////////////////////////////////////////////////////////////////////////////

bool Asura_PSP_SCEUtility_FileListHandler::Update (bool& bCancelled)
{
	// Which keys have we pressed?
	if (Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_ENTER))
	{
		// Enter - perform the appropriate file operation...
		bCancelled	= false;

		if (0 < m_iNumSlots)
		{
			OnSelect	(*m_ppxFileData [m_iCurrentSlot]);
		}

		return	(false);
	}

	else if (Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_ESCAPE))
	{
		// Enter - cancel the file operation...
		bCancelled	= true;

		return	(false);
	}

	else
	{
		// What about menu movement?
		if (Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_UP))
		{
			// Up - go up one slot...
			m_iCurrentSlot	= Asura_Maths::Max ((m_iCurrentSlot - 1), 0);
		}

		else if (Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_PAGEUP))
		{
			// Up - go to the top of the list...
			m_iCurrentSlot	= 0;
		}

		else if (Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_DOWN))
		{
			// Down - go down one slot...
			m_iCurrentSlot	= Asura_Maths::Min ((m_iCurrentSlot + 1), (m_iNumSlots - 1));
		}

		else if (Asura_UserInput::DebouncedKeyPressed(ASURA_KEYID_PAGEDOWN))
		{
			// Page-down - go to the end of the list...
			m_iCurrentSlot	= m_iNumSlots - 1;
		}

		// Continue what we were doing...
		return	(true);
	}
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::Update'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_PSP_SCEUtility_FileListHandler::Render
// Author       : Andy Tate
// Date         : 5-Oct-2005
//
// Description  : Handles the rendering of the SCE Utility file-list.
//
// Return value : None.
////////////////////////////////////////////////////////////////////////////////

void Asura_PSP_SCEUtility_FileListHandler::Render (void)
{
	const float	fScreenScale	= CalculateScreenScale ();

	// Render the title...
	RenderTitle	(fScreenScale);

	// Do we have any data to render?
	if (0 == m_iNumSlots)
	{
		// No - render an error message...
		RenderNoSlotsMessage	(fScreenScale);
	}

	else
	{
		const int								iTopSlot			= m_iCurrentSlot - (g_uFileListMaxVisibleSlots / 2);
		const int								iBottomSlot			= m_iCurrentSlot + (g_uFileListMaxVisibleSlots / 2);
		const Asura_PSP_SCEUtility_FileData&	xCurrentFileData	= *m_ppxFileData [m_iCurrentSlot];

		Asura_IntVector_2						xIntPosition (g_xFileListFirstSlotPosition);

		// Yes - go through each slot in-turn...
		for (int s = iTopSlot; s <= iBottomSlot; s++)
		{
			// Is this slot within range?
			if ( (s >= 0) && (s < m_iNumSlots) )
			{
				const Asura_PSP_SCEUtility_FileData&	xFileData	= *m_ppxFileData [s];
				const u_int								uColour		= (s == m_iCurrentSlot) ? 0xFFFFFFFF : 0xFF808080;
				const Asura_UnicodeChar*				wszText		= (NULL == xFileData.GetTitle())
																	? L"EMPTY"
																	: xFileData.GetTitle();

				Asura_Vector_2							xPosition;

				// Yes - calculate the text position...
				CalculateScreenPosition	(fScreenScale, xIntPosition, xPosition);

				// Print the data...
				Asura_Font_System::PrintLongString
				(
					wszText,
					NULL,
					xPosition [0],
					xPosition [1],
					1.0f,
					0.5f * fScreenScale,
					uColour,
					ASURA_TEXTFORMAT_LEFTJUSTIFIED
				);
			}

			// Increment the slot position...
			xIntPosition	+= g_xFileListSlotIncrement;
		}

		// Do we have a valid save-slot?
		if (NULL == xCurrentFileData.GetTitle())
		{
			// Render the empty slot-data...
			RenderEmptySlot	(fScreenScale, xCurrentFileData);
		}

		else
		{
			// Render the slot-data...
			RenderSlot	(fScreenScale, xCurrentFileData);
		}
	}
}

/// End of function 'Asura_PSP_SCEUtility_FileListHandler::Render'. ///


/// End of file. ///
