//-------------------------------------------------------------------------------------------------
// <copyright file="SEController.cpp" company="LiquidRobotics">
//  Copyright (c) Liquid Robotics Corporation, confidential and proprietary.  All rights reserved. 
// </copyright>
//
// <summary>
// 	Implementation of the SEController class, which implements the controller
//  role business logic for the interface to an example sensor.
// </summary>
//
// <owner>Mike Cookson</owner>
//-------------------------------------------------------------------------------------------------

#include "LqrSMACByteArray.h"
#include "LqrSMACLogger.h"
#include "SEController.h"
#include "SensorControllerRunFileCmd.h"
#include "SETestCommand.h"

using namespace std;
using namespace LiquidRobotics::SMACFramework;

namespace LiquidRobotics {
namespace SensorExample {

SEController::SEController(const SEControllerSettings& _settings, IObjectBroker& _broker, Logger& _logger, GPSSignalSubscriber::Ptr _gpsSubscriber, ShutdownSignalSubscriber::Ptr _shutdownSubscriber)
: SEControllerBase(_broker, _logger, _gpsSubscriber, _shutdownSubscriber)
, settings(_settings)
, lat(0)
, lon(0)
, hasGPS(false)
{
}

SEController::~SEController()
{
}

void SEController::Initialize()
{
	bool shutdownBase = false;

	try
	{
		SEControllerBase::Initialize();
		shutdownBase = true;
		serialPort = settings.GetSerialPortSettings().CreatePort();
		serialListener.reset(new SerialListener(*serialPort, settings.GetSerialListenerSettings()));
		serialListenerConnection = serialListener->Subscribe(boost::bind(&SEController::OnSerialReceive, this, _1, _2));
		serialListener->Initialize();
	}
	catch(...)
	{
		serialListener.reset();
		serialPort.reset();

		if (shutdownBase)
			try { Base::Shutdown() ; } catch(...) { }

		throw;
	}

}

void SEController::Shutdown()
{
	serialListenerConnection.reset();

	SerialListenerPtr sl = serialListener;

	if (sl)
	{
		serialListener.reset();
		try { sl->Shutdown(); } catch(...) { }
		sl.reset();
	}

	serialPort.reset();

	try { Base::Shutdown() ; } catch(...) { }
}

void SEController::OnGPSSampleEvent(const GPSSampleEvent& sample)
{
	if (sample.HasGPS())
	{
		sample.GetGPS(lat, lon);
		hasGPS = true;
	}
}

void SEController::OnSerialReceive(SerialListener& sender, const ByteArray& receivedData)
{
}

void SEController::OnShutdownEvent()
{
	Base::OnShutdownEvent();
}

SEController::ScopedConnectionPtr SEController::SubscribeReportedTag(ReportedTagSignalType::slot_type slot)
{
	ScopedConnectionPtr result;
	result.reset(new ScopedConnection(reportedTagSignal.connect(slot)));
	return result;
}

SEController::CommandPtr SEController::ParseCommand(ParsingContext& context, bool internalCmd)
{
	CmdLineParser parser(context.GetCmd());
	CommandPtr result;

	if (!!(result = EventLib::SensorControllerRunFileCmd<TCon,TCmd,TCID,TEx>::Parse("SEMGR", "--run", *this, parser, context, logger))
	 || !!(result = SETestCommand::Parse("SEMGR", "TEST", *this, parser, context, logger)))

		;

	else
	{
		stringstream msg;
		msg << "Unrecognized command '" << context.GetCmd() << "'";

		throw invalid_argument(msg.str());
	}

	return result;
}

}
}
