//-------------------------------------------------------------------------------------------------
// <copyright file="LogListenerProgram.cpp" company="LiquidRobotics">
//  Copyright (c) Liquid Robotics Corporation, confidential and proprietary.  All rights reserved. 
// </copyright>
//
// <summary>
// 	Implementation of LogListenerProgram class, which listens to log messages
//  coming from the Float and saves them to a file
// </summary>
//
// <owner>Arash Ushani</owner>
//-------------------------------------------------------------------------------------------------

#include "LogListenerProgram.h"
#include "LogListenerProgramSettings.h"
#include "EventPropertyValue.h"
#include "LqrSMACGetErrorDescription.h"
#include "LqrSMACLogger.h"
#include "LqrSMACPayloadDescription.h"
#include "LqrSMACFileSet.h"

using namespace std;
using namespace boost;
using namespace CORBA;
using namespace LiquidRobotics::EventLib;
using namespace LiquidRobotics::SMAC;
using namespace LiquidRobotics::SMACFramework;

namespace LiquidRobotics {
namespace LogListener {


LogListenerProgram::LogListenerProgram(IObjectBroker& _broker, const LogListenerProgramSettings& _settings, Logger& _logger, FileSet& _floatLogFile)
: EventTransceiver(_settings.GetEventTransceiverSettings(), _broker, _logger)
, broker(_broker)
, settings(_settings)
, logger(_logger)
, floatLogFile(_floatLogFile)
{
}

LogListenerProgram::~LogListenerProgram()
{
}

void LogListenerProgram::Initialize(Object_ptr _pServer, PayloadManagerClient::Ptr _pmClient)
{
	pmClient = _pmClient;

	// subscribe to the shutdown event
	SignalForEventName(settings.GetShutdownEvent().GetName());

	// initializing event transceiver
	EventTransceiver::Initialize(_pServer);

	// initialize timer collection
	timerCollection.Initialize();

	logger.Info << "Log Listener Version 1.0.106" << endl;

	stringstream msg;
	msg << "<Initializing Log Listener>";

	try
	{
		floatLogFile.Init();
		floatLogFile.WriteLine(msg.str());

		//floatLogFile.WriteLine(settings.GetLoggerSettings().ToString());
		//floatLogFile.WriteLine(settings.GetFloatLogSettings().ToString());

		logger.Info << "Created Float Log File" << endl;
	}
	catch (...)
	{
		logger.Info << "Exception creating Float Log File" << endl;
	}

}

::CORBA::Double LogListenerProgram::Ping()
{
	using namespace LiquidRobotics::SMACFramework;
	stringstream msg;
	msg << "LogListenerProgram::Ping: ";

	::CORBA::Double result;
	timeval tv;
	int status = gettimeofday(&tv, NULL);
	int errSave = errno;

	if (!status)
	{
		result = tv.tv_usec;
		result /= 1000000.0;
		result += tv.tv_sec;
	}
	else
	{
		msg << "(gettimeofday returned error #" << errSave << " '" << GetErrorDescription(errSave) << "') ";
		result = 0;
	}

	Logger::Lock logLock(logger);
	logger.Info.precision(15);
	logger.Info << msg.str() << result << endl;
	return result;
}

::LiquidRobotics::SMAC::EnumerationData* LogListenerProgram::GetEnumerationData()
{
	EnumerationData_var result;
	result = new EnumerationData;
	return result._retn();
}

void LogListenerProgram::PowerOff(::LiquidRobotics::SMAC::PowerOffTimeType offDelay)
{
	logger.Info << "PowerOff offDelay=" << offDelay << endl;
}

void LogListenerProgram::PowerOn()
{
	logger.Info << "PowerOn" << endl;
}

::LiquidRobotics::SMAC::BoardIDType LogListenerProgram::boardID()
{
	return pmClient->GetMyBoardID();
}

::LiquidRobotics::SMAC::PayloadDescription* LogListenerProgram::description()
{
	Desc::CORBAEntity_var result = settings.GetPayloadManagerClientSettings().GetPayloadDescription().GetEntity();
	return result._retn();
}

::LiquidRobotics::SMAC::EPayloadEnableState LogListenerProgram::enableState()
{
	return EPES_ENABLED;
}

::LiquidRobotics::SMAC::PowerOffTimeType LogListenerProgram::requestOffTime()
{
	return (PowerOffTimeType) 0;
}

::LiquidRobotics::SMAC::PowerOnTimeType LogListenerProgram::requestOnTime()
{
	return (PowerOnTimeType) 0;
}

::LiquidRobotics::SMAC::ComponentVersion* LogListenerProgram::softwareVersion()
{
	ComponentVersion_var result;
	result = new ComponentVersion;
	result->versionString = CORBA::string_dup("1.0.0");
	result->majorVersion = 1;
	result->minorVersion = 0;
	result->subminorVersion = 0;
	return result._retn();
}

::LiquidRobotics::SMAC::TaskIDType LogListenerProgram::taskID()
{
	return pmClient->GetMyTaskID();
}

void LogListenerProgram::SendCommand(const ::CORBA::Any& command, const char* requester, const char* transactionID, ::CORBA::Any_OUT_arg result)
{
	using namespace LiquidRobotics::SMACFramework;


	const char* cmd0;

	if (!(command >>= cmd0))
	{
		logger.Error << "Incoming command type is not a string" << endl;
		ThrowCORBAException2<BadParameter>();
	}

	logger.Info << "Log Listener Command:" << cmd0 << "' requester='" << requester << "' transactionID='" << transactionID << "'";


	time_t t = time(NULL);
	struct tm tmBuf;
	gmtime_r(&t, &tmBuf);
	char charBuf[200];
	asctime_r(&tmBuf, charBuf);
	charBuf[strcspn(charBuf, "\r\n")] = '\0';

	stringstream stm;
	stm << "Time=" << charBuf;

	const string resultStr = stm.str();
	logger.Info << " returning result='" << resultStr << "'" << endl;

	try
	{
		floatLogFile.Write((const string) cmd0);
	}
	catch (...)
	{
		logger.Info << cmd0 << endl;
		logger.Info << "Exception writing console message: " << cmd0 << endl;
	}

	result.ptr() = new Any;
	*result.ptr() <<= resultStr.c_str();
}

void LogListenerProgram::ShutdownHandler(EventTransceiver& sender, const IEventBase& receivedEvent)
{
	broker.QueueShutdown();
}

}
}
