/*******************************************************************************
 * Copyright (c) 2005, 2009 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andy Kaylor, Intel - Initial re-implementation of Agent Controller
 * 
 * $Id: LoggingService.c,v 1.22 2009/02/04 20:28:51 jwest Exp $
 *******************************************************************************/ 

#include "LoggingService.h"
#include "LoggingServicePrivate.h"
#include "tptp/TPTPOSCalls.h"
#include "tptp/NoLog.h"
#include <stdio.h>
#ifndef _WIN32
 #include <string.h>
#endif

#define CONFIG_DIR_WITH_PARENT	"../config/"

tptp_int32 loggingService_init( LoggingService_t* ls )
{
	ls->file = (tptp_filehandle)-1;
	ls->loggingDirectory[0] = '\0';
	ls->loggingFormat = TPTP_LOGFORMAT_CBE;
	ls->loggingLevel = TPTP_CRITICAL;
	ls->loggingEnabled = TRUE;
	return 0;
}

tptp_int32 loggingService_cleanup( LoggingService_t* ls )
{
	if ( ls->file != (tptp_filehandle)-1 )
	{
		tptp_closeLogFile( ls->file );
	}
	return 0;
}

void loggingService_disableLogging( LoggingService_t* ls )
{
	/* This is used in the case of the shutdown processing, where another AC is already using the log file */
	ls->loggingEnabled = FALSE;
}

tptp_int32 loggingService_setLoggingLevel( LoggingService_t* ls, tptp_int32 level )
{
	ls->loggingLevel = level;
	return 0;
}

tptp_int32 loggingService_setLoggingFormat( LoggingService_t* ls, tptp_loggingFormat format )
{
	ls->loggingFormat = format;
	return 0;
}

tptp_int32 loggingService_setLogDirectory( LoggingService_t* ls, const tptp_string* dir )
{
	char *logFile = NULL;
	int lenDirName = 0;
	int rc = 0;
	
	if ( !ls->loggingEnabled )
	{
		return 0;
	}
	
	/* If we've created a file before... */	
	if ( ls->file != (tptp_filehandle)-1 )
	{
		/* If the directory is unchanged, do nothing */
		if ( ((dir == NULL) && (ls->loggingDirectory == '\0')) ||
		     ((dir != NULL) && (0 == compareIgnoreCase( dir, ls->loggingDirectory ))) )
		{
			return 0;
		}
		/* Close the old log file */
		tptp_closeLogFile( ls->file );
	}

	/* Set the directory name for the log file. */
	/* If log directory not specified, default to same dir as agent controller. */
	if (!dir)
	{
		strcpy( ls->loggingDirectory, CONFIG_DIR_WITH_PARENT );
	} else
	{
		strcpy( ls->loggingDirectory, dir );
	}

	lenDirName = strlen(ls->loggingDirectory); //need this several places, so get it once

	/* Now build up the name of the log file and open it. */
	/* Allocate space for the full logfile name, including file separator and null terminator */
	logFile = (char *)tptp_malloc( lenDirName + 1 + strlen(AC_LOG_FILE_NAME) + 1 );
	if ( logFile == NULL )
	{
		/* Failed to allocate enough space to include the path, so just
		 * create the file in the current directory w/o specifying a path
		 * and reset the log dir setting to match.
		 */
		strcpy( ls->loggingDirectory, CONFIG_DIR_WITH_PARENT );
		tptp_createLogFile( AC_LOG_FILE_NAME, &ls->file );
		return 0;
	}

	strcpy( logFile, ls->loggingDirectory );
	if ( logFile[lenDirName-1] != FILE_SEPARATOR )
	{
		logFile[lenDirName] = FILE_SEPARATOR;
		logFile[lenDirName+1] = '\0';
	}

	strcat( logFile, "servicelog.log" );
	
	/* Open a new log file */
	rc = tptp_createLogFile( logFile, &ls->file );
	tptp_free(logFile);
	return rc;
}

tptp_int32 loggingService_logEvent( LoggingService_t* ls, 
                                    tptp_string*      subcomponent,
                                    tptp_uint32       instanceId,
                                    tptp_string*      filename, 
                                    tptp_int32        lineNum, 
                                    tptp_int32        severity, 
                                    tptp_string*      event )
{
	tptp_string* cbeStr;
	tptp_int32   rc = 0;
	int len;

	if ( !ls->loggingEnabled )
	{
		return 0;
	}

	/* Filter based on logging level */
	if ( severity < ls->loggingLevel )
	{
		return 0;
	}

	len = strlen(event);
	if (len > 0 && *(event + len - 1) == '\n') {
		*(event + len - 1) = '\0'; 
	} 

	if ( (ls->loggingFormat == TPTP_LOGFORMAT_CBE) && 
	     (0 == tptp_createLogCBE( "AgentController", subcomponent, instanceId, filename, lineNum, severity, event, &cbeStr )) )
	{
		if(ls->file != -1)  {
			rc = loggingService_logCBE( ls, cbeStr );
			tptp_free( cbeStr );
		}
	}
	else
	{
		tptp_int32   bytesWritten;

		if(ls->file != -1)  {
			rc = tptp_writeToLogFile( ls->file, event, &bytesWritten );
		}
	}
	
	return rc;
}

tptp_int32 loggingService_logCBE( LoggingService_t*  ls, 
                                  const tptp_string* cbeStr )
{
	tptp_int32   bytesWritten;

	if ( !ls->loggingEnabled )
	{
		return 0;
	}

	return tptp_writeToLogFile( ls->file, cbeStr, &bytesWritten );
}

tptp_int32 loggingService_processCommand( LoggingService_t* ls, const char* cmd )
{
	tptp_int32     ret;
	tptp_int32     sourceID;
	tptp_int32     context;
	char*          interfaceID = 0;
	char*          cmdName = 0;
	tptp_list_t*   paramList;

	if ( !ls->loggingEnabled )
	{
		return 0;
	}

	/* Parse the XML into useful blocks */
	ret = parseCommand( cmd, &sourceID, &context, 
	                    &interfaceID, &cmdName, &paramList );
	if ( ret != 0 )
	{
		/* TODO: Report error */
		return ret;
	}
	else
	{
		ret = loggingService_processCommandImpl( ls,
		                                         cmd, 
		                                         sourceID, 
		                                         context,
		                                         interfaceID, 
		                                         cmdName, 
		                                         paramList );

		/* Free the resources allocated by parseCommand */
		tptp_free( interfaceID );
		tptp_free( cmdName );
		tptp_list_clear( paramList );
		tptp_free( paramList );

		return ret;
	}
}

tptp_int32 loggingService_processCommandImpl( LoggingService_t*   ls,
                                              const tptp_string*  cmd, 
                                              tptp_int32          sourceID, 
                                              tptp_int32          context,
                                              const tptp_string*  interfaceID, 
                                              const tptp_string*  cmdName, 
                                              tptp_list_t*        paramList )
{
	tptp_int32 ret;

	/* Find the right interface */
	if ( isEqualString( interfaceID, "org.eclipse.tptp.platform.loggingService" ) )
	{
		/* Find the right command */
		if ( isEqualString( cmdName, "logEvent" ) )
		{
			tptp_string* event;
			int dontFree = 0;

			ret = getStringParam( "event", paramList, &event );
			if ( ret != 0 )
			{
				return TPTP_CMD_BAD_ARG;
			}

			if ( strlen( event ) == 0 )
			{
				event = (char *)cmd;
				dontFree = 1;
			}

			/* Process this command */
			ret = loggingService_logCBE( ls, event );			

			/* free the agent name string */
			if ( !dontFree )
				tptp_free( event );

			return ret;
		}
		else
		{
			/* TODO: Report unrecognized command */
			return -1;
		}
	}
	else
	{
		/* TODO: Report unrecognized interface */
		return -1;
	}

	return 0;
}
