//
// Asura_PlatformLogfile.cpp
//
// Created by KJFL - Wednesday, February 04, 2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#include "Core/Asura.h"

// This file's header.
#include "Debugging/Asura_Logfile.h"
// Asura headers
#include "Core/Asura_PlatformBasics.h"
#include "Core/Asura_String.h"
// PSP headers
#ifdef ASURA_PSP_ARTIST_BUILD
#include <fatms.h> // needed for checking memory stick presence
#endif // defined(ASURA_PSP_ARTIST_BUILD)
#include<kernel.h>

static const int LOGFILE_OUTPUT_BUFFER_SIZE = 1024;
static const int LOGFILE_NAME_SIZE = 256;

//static const Asura_Char*	File;
//static unsigned int			Line;
//static Asura_NameTree		OpenedLogfiles;

static char g_szHostFileName[LOGFILE_NAME_SIZE];

// Logfile allowed in artist builds but not any other disc builds
#if defined(ASURA_PSP_ARTIST_BUILD) || !defined(ASURA_PSP_UMD)
#define ASURA_PSP_LOGFILE_ALLOWED (1)
#endif

#if defined(ASURA_PSP_ARTIST_BUILD) && !defined(ASURA_LOGFILES_ENABLED)
#error ASURA_LOGFILE_ENABLED not defined in ASURA_PSP_ARTIST_BUILD
#endif //defined(ASURA_PSP_ARTIST_BUILD) && !defined(ASURA_LOGFILES_ENABLED)

bool __Asura_OverrideLogfilesDir( const char* szDir, bool bArchiveExisting )
{
	return false;
}

// Helper functions
static const char* GetHostFileName(const char* szFileName)
{
#ifdef ASURA_PSP_ARTIST_BUILD
	Asura_PrintfToBfr(g_szHostFileName, "ms0:%s", LOGFILE_NAME_SIZE, true, szFileName);
#else
	Asura_PrintfToBfr(g_szHostFileName, "host0:%s", LOGFILE_NAME_SIZE, true, szFileName);
#endif
	return g_szHostFileName;
}

static void WriteToFile(const char* szFileName, const char* szData, int iNumChars)
{
#ifdef ASURA_PSP_LOGFILE_ALLOWED
#ifdef ASURA_PSP_ARTIST_BUILD
	// Can't write logfiles without a memory stick assigned.
	if(sceFatmsIsAssigned() != 1)
	{
		return;
	}
#endif
    // Output.
	int iHandle = sceIoOpen (GetHostFileName(szFileName), SCE_O_CREAT | SCE_O_APPEND | SCE_O_WRONLY, 0);
	if(iHandle >= 0)
	{
		sceIoLseek(iHandle, 0, SEEK_END);
		// write data
		sceIoWrite(iHandle, szData, iNumChars);
		// Close file
		sceIoClose(iHandle);
	}
	else
	{
		sceKernelPrintf("Failed to open file %s (error 0x%x)\n", GetHostFileName(szFileName), iHandle);		
	}
#endif//def ASURA_PSP_LOGFILE_ALLOWED
}

static bool Asura_LogfileClear(const Asura_Char* szFileName)
{
#ifdef ASURA_PSP_LOGFILE_ALLOWED
#ifdef ASURA_PSP_ARTIST_BUILD
	// Can't write logfiles without a memory stick assigned.
	if(sceFatmsIsAssigned() != 1)
	{
		return false;
	}
#endif
	// First ensure that the directory exists.
	// Can't do this using Asura_Strings because they allocate,
	// and the first allocation clears the logfile, which allocates,
	// which clears the logfile...
	char szHostPath[LOGFILE_NAME_SIZE];
	strncpy(szHostPath, szFileName, LOGFILE_NAME_SIZE);
	char* pcCurrentChar = &szHostPath[strlen(szHostPath)];
	// Replace the last slash with a null zero.
	while(pcCurrentChar != &szHostPath[0])
	{
		if(*pcCurrentChar == '\\')
		{
			*pcCurrentChar = 0;
			break;
		}
		--pcCurrentChar;
	}
	sceIoMkdir(GetHostFileName(szHostPath), 0);

	// Now create/clear the file itself
	int iHandle;
	if ((iHandle = sceIoOpen (GetHostFileName(szFileName), SCE_O_CREAT | SCE_O_WRONLY | SCE_O_TRUNC, 0)) < 0)
	{
		return false;        // An error occured!
	}

	// Close file
	sceIoClose(iHandle);
#endif//def ASURA_PSP_LOGFILE_ALLOWED
	return true;
}

void __Asura_LogfileDebugData(const Asura_Char* file, unsigned int line)
{
//	File = file;
//	Line = line;
}

void __Asura_LogfileOutput(const Asura_Char* szFileName, const Asura_Char* szFormat, ...)
{
	char buffer[LOGFILE_OUTPUT_BUFFER_SIZE];

	va_list xArgs;
	va_start( xArgs, szFormat );
    u_int uLen = Asura_PrintfToBfr( buffer, szFormat, xArgs, LOGFILE_OUTPUT_BUFFER_SIZE, true );
	va_end( xArgs );
	WriteToFile(szFileName, buffer, uLen);
}

// This version of the log clear function should not make use of any globals
// with constructors or any functions that use some. In particular, this
// function can't assert or use the OpenedLogfiles tree to check if the file's
// been used before or not.
void __Asura_SimpleLogfileClear(const Asura_Char* file)
{
    Asura_LogfileClear( file );
}

// This version of the logging function should not make use of any globals
// with constructors or any functions that use some. In particular, this
// function can't assert or use the OpenedLogfiles tree to check if the file's
// been used before or not.
void __Asura_SimpleLogfileOutput(const Asura_Char* szFileName, const Asura_Char* szFormat, ...)
{
	char buffer[LOGFILE_OUTPUT_BUFFER_SIZE];

	va_list xArgs;
	va_start( xArgs, szFormat );
    u_int uLen = Asura_PrintfToBfr( buffer, szFormat, xArgs, LOGFILE_OUTPUT_BUFFER_SIZE, true );
	va_end( xArgs );

	WriteToFile(szFileName, buffer, uLen);
}

void __Asura_OutputToDebugger( const Asura_Char* szFormat, ... )
{
	char szBuffer[LOGFILE_OUTPUT_BUFFER_SIZE];

	va_list xArgs;
	va_start( xArgs, szFormat );
    Asura_PrintfToBfr( szBuffer, szFormat, xArgs, LOGFILE_OUTPUT_BUFFER_SIZE, true );
	va_end( xArgs );

	// Output.
	sceKernelPrintf( "%s", szBuffer );
}


bool __Asura_Logfile_CanLogYet( void )
{
	return true;	
}

void __Asura_SimpleLogfileOutput_PreFormatted( const char* szLogFilename, const char* szStr, u_int uLen )
{
	WriteToFile(szLogFilename, szStr, uLen);
}

