//------------------------------------------------------------------------------
// <copyright file="main.cpp" company="LiquidRobotics">
//
// Copyright (c) 2014 Liquid Robotics, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// This software is associated with a release.  Liquid Robotics makes no
// representation that the design, interfaces or component distribution will
// remain unchanged in future releases.
//
// </copyright>
//
// <summary>
// 	main() function for DemoSensor
// </summary>
//
// <owner>Mike Cookson</owner>
//------------------------------------------------------------------------------

#include <iostream>
#include <string>
#include "LqrSMACStdOutLogger.h"
#include "LqrSMACObjectBroker.h"
#include "LqrSMACIObjectBroker-inline.h"
#include "LqrSMACObjectBroker-inline.h"
#include <stdlib.h>
#include <boost/foreach.hpp>
#include "LqrSMACIdl.h"
#include "DemoSensor.h"
#include "DemoSensorSettings.h"
#include "PayloadManagerClient.h"

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

int main(int argc, char* argv[])
{
	int retcode = 0;				// return code form main

	// update the time zone settings from the environment
	tzset();

	try
	{
		// instantiate a "settings" class and deserialize it from the
		// configuration XML file (typically uses boost serialization)
		DemoSensorSettings settings;
		settings.Load("DemoSensor-config.xml");

		// read out the name name of the CORBA server from the settings
		// and instantiate a logger instance that will be used for
		// debug output (written to standard output)
		const string serverName = settings.GetServerName();
		StdOutLogger logger(serverName.c_str(), 1, Logger::LT_DEBUG);

		// instantiate the interface to the CORBA object broker and
		// initialize it with parameters from the command line
		ObjectBroker broker(true);
		broker.Initialize(argc, argv);

		// instantiate DemoSensor (my server class), which implements the
		// interface functions defined in the CORBA IDL file for
		// IDemoSensorWithEvents (note that most sensors will use
		// ISensorWithEvents instead)
		DemoSensor demoSensor(broker, settings, logger);

		// create a "tie" class for ISensorWithEvents and point it to
		// my DemoSensor instance: a tie class derives from the abstract
		// base class defined by the interface (ISensorWithEvents in this case)
		// and subclasses the target object (demoSensor) so that the target
		// doesn't have to derive from the abstract base class
		PortableServer::ServantBase_var theServer = 0;
		theServer = new ::POA_LiquidRobotics::SMAC::ISensorWithEvents_tie<DemoSensor>(demoSensor);

		// advertise the instance (theServer, a CORBA pointer to the target
		// instance, demoSensor)
		Object_var serverRef = broker.AdvertizeInstance(theServer.in(), serverName.c_str());

		// instantiate the payload manager client, which interfaces PayloadManager
		// and passes it information about this process); the XML file contains
		// settings that the client will use
		PayloadManagerClient::Ptr pmClient;
		pmClient.reset(new PayloadManagerClient(settings.GetPayloadManagerClientSettings(), broker, demoSensor));

		// initialize the server class: note that PayloadManagerClient is not
		// registered yet, so the board address is not final
		demoSensor.Initialize(serverRef.in(), pmClient);

		// register PayloadManagerClient; DemoSensor derives from EventTransceiver,
		// and PayloadManagerClients needs that to be initialized before it can
		// register
		pmClient->Register(serverRef.in());

		// now listen for requests; this function will not return until the object
		// broker (broker) indicates an error or its "Shutdown" method is called
		// (use QueueShutdown from the server class)
		broker.ListenForRequests();
	}
	// catch any CORBA exceptions from a high level: note that CORBA exceptions are
	// not derived from the STL exception class)
	catch(CORBA::Exception& ex)
	{
		cerr << "Caught CORBA exception: " << DecodeCORBAException(ex) << endl;
		retcode = 1;
	}
	// catch any STL exceptions from a high level
	catch(exception& ex)
	{
		cerr << "Caught " << typeid(ex).name() << ": " << ex.what() << endl;
		retcode = 1;
	}

	return retcode;				// returning the result code
}
