/**
*
* \file Asura_Chunk_LocalText.cpp
*
* Created by James Paulin - 30/07/2002 12:05:07
*
* Copyright (C) 2002 Rebellion, All Rights Reserved.
*
* \brief
*
**/

#include "Core/Asura.h"

#include "ChunkSystem/Asura_Chunk_LocalText.h"

#include "ChunkSystem/Asura_Chunk_Loaders.h"
#include "Core/Asura_LocalisedText.h"	
#include "Core/Asura_String.h"
#include "Debugging/Asura_Assert.h"
#include "FileAccess/Asura_FileAccess.h"

// JP:  We make use of preprocessor directives here to stop the flexilex utility
//		from trying to include the enum header it is used to create (!)
#ifndef _FLEXILEX

bool Asura_Chunk_LocalText::Process(Asura_Handle fileHandle) const
{
	Asura_Assert( Version <= CHUNK_LOCAL_TEXT_VERSION, "Chunk version is greater than highest supported!" );
	if( Version > CHUNK_LOCAL_TEXT_VERSION ) return false;

    if (Version < 3)
    {
        Asura_Assert( false, "Outdated Asura_Chunk_LocalText version. Re-export your level." );
        return false;
    }

    Asura_Assert( Asura_LocalisedText::IsOperational(), "Should get here via Asura_LocalisedText::Initialise()." );
	
	// text files now store a language number 
	u_int uBytesForLanguageNumber = 0;

	Asura_LocalisedText_Language eLang = Asura_LocalisedText::GetCurrentLanguage();
	if( Version >= 4 )
	{
		int iLang;
		Asura_FileAccess::ReadData( fileHandle, &iLang, sizeof(int) );
		eLang = static_cast<Asura_LocalisedText_Language>( iLang );

		uBytesForLanguageNumber += sizeof(int);
	}	

	// need to skip this chunk if it is not the current in-use language	
	if( Asura_LocalisedText::GetCurrentLanguage() != eLang ) { return false;	 }
	
	// allocate storage for strings
	if( !Asura_LocalisedText::AllocateStringPtrArray(NumEntries) ) { return false; }

	// (MH - 22.04.2004) instead of doing a new for each string, allocate enough space
	// to hold all the strings and copy the string data to that. Each string is preceded
	// by an int indicating length.
	u_int uSizeForStrings = this->Size - sizeof(Asura_Chunk_LocalText);
	uSizeForStrings -= NumEntries * sizeof(int);
	uSizeForStrings -= uBytesForLanguageNumber;
	char* pcTextBuffer = Asura_LocalisedText::AllocateStringBuffer(uSizeForStrings);

	if (!pcTextBuffer) return false;

	Asura_UnicodeChar* wszBuffer = reinterpret_cast<Asura_UnicodeChar*>(pcTextBuffer);

	for(int i = 0; i < NumEntries; i++)
	{
		int iLength;
        Asura_FileAccess::ReadData( fileHandle, &iLength, sizeof(int) );

		Asura_FileAccess::ReadData( fileHandle, wszBuffer, iLength * sizeof(Asura_UnicodeChar) );

        // (MP - 07.07.2003) NB: Length includes the nul terminator here,
        // unlike every other C string ever.
		wszBuffer[iLength - 1] = '\0';

		Asura_LocalisedText::AddString(i, wszBuffer);
		
		wszBuffer += iLength;
	}

	Asura_Assert(reinterpret_cast<char*>(wszBuffer) == pcTextBuffer + uSizeForStrings, "error in string allocation");
    
	return true;
}

#else

//DUMMY CHUNK PROCESS FOR USE WITH FLEXILEX
//this dummy does not call CreateString()
bool Asura_Chunk_LocalText::Process(Asura_Handle fileHandle) const
{
	return false;
}

#endif


/**************/
/* Page chunk */
/**************/

void Asura_Chunk_LocalText_Page::Create(void)
{
	// ALL .ASR CREATION CODE IS PERFORMED FROM WITHIN THE FLEXILEX PROJECT
	// (FlexiLex.cpp)
}

#if ASURA_LOCALISEDTEXT_PAGE_STORAGE_SIZE > 0

bool Asura_Chunk_LocalText_Page::Process( Asura_Handle iFileHandle ) const
{	
	Asura_Assert( Version <= CHUNK_LOCAL_TEXT_PAGE_VERSION, "Chunk version is greater than highest supported!" );
	if( Version > CHUNK_LOCAL_TEXT_PAGE_VERSION ) return false;

    Asura_Assert( Asura_LocalisedText::IsOperational(), "Call Asura_LocalisedText::Initialise() before loaded localised text pages." );

	u_int uBytesForLanguageNumber = 0;

	// pages now store a language number 
	Asura_LocalisedText_Language eLang = ASURA_LT_L_ENGLISH;
	if( Version >= 5 )
	{
        int iLang;
        Asura_FileAccess::ReadData( iFileHandle, &iLang, sizeof(int) );
        eLang = static_cast<Asura_LocalisedText_Language>( iLang );

		uBytesForLanguageNumber += sizeof(int);
    }	

	// need to skip this chunk if it is not the current in-use language	
    if( Asura_LocalisedText::GetCurrentLanguage() != eLang ) { return false;	 }

	// pages now store a name for tools purposes if ASURA_TOOLS is defined
	u_int uBytesForPageName = 0;
#ifdef ASURA_TOOLS
	const Asura_Char* szPageName = NULL;
#endif //#ifdef ASURA_TOOLS
	if(Version >= 4)
	{
		u_int uIntsForPageName = 0;
#ifdef ASURA_TOOLS
		szPageName = Asura_FileAccess::ReadString( iFileHandle, NULL, &uIntsForPageName );
#else
		Asura_FileAccess::ReadString( iFileHandle, NULL, &uIntsForPageName );
#endif 
		uBytesForPageName = uIntsForPageName * 4;
	}
	
	// (MH - 22.04.2004) instead of doing a new for each string, allocate enough space
	// to hold all the strings and copy the string data to that. Each string is preceded
	// by an int indicating length.
	// we have to waste the space for the page name, which is only used in tools
	u_int uSizeForStrings = this->Size - sizeof(Asura_Chunk_LocalText_Page);
	uSizeForStrings -= m_uNumEntries * sizeof(int);
	uSizeForStrings -= uBytesForLanguageNumber;
	uSizeForStrings -= uBytesForPageName;

	Asura_LocalisedText_Page* pxPage = Asura_LocalisedText::AddPage( m_uHashID, m_uNumEntries, uSizeForStrings );
    if( !pxPage ) { return false; }

#ifdef ASURA_TOOLS
	if(Version >= 4)
	{
		pxPage->m_xToolsName = szPageName;
	}	
#endif 

	char* const pcStringBuffer = pxPage->GetStringBuffer();
	if (!pcStringBuffer) return false;

	Asura_UnicodeChar* wszBuffer = reinterpret_cast<Asura_UnicodeChar*>(pcStringBuffer);

	for( u_int u=0; u<m_uNumEntries; u++ )
	{
		int iLength;
		Asura_FileAccess::ReadData( iFileHandle, &iLength, sizeof(int) );
		

		Asura_FileAccess::ReadData( iFileHandle, wszBuffer, iLength * sizeof(Asura_UnicodeChar) );
			
        // (MP - 07.07.2003) NB: Length includes the nul terminator here,
        // unlike every other C string ever.
		wszBuffer[iLength - 1] = '\0';

		pxPage->AddString(u, wszBuffer);
		wszBuffer += iLength;
	}

	Asura_Assert( reinterpret_cast<char*>(wszBuffer) == pcStringBuffer + uSizeForStrings, "string allocation bug");
	return true;
}

#else

bool Asura_Chunk_LocalText_Page::Process( Asura_Handle iFileHandle ) const
{
    Asura_Assert( false, "Localised text pages not supported; why is this chunk here?" );
    return false;
}

#endif
