//------------------------------------------------------------------------------------------------
// <copyright file="DemoSensorSettings.h" 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>
// 	Declarations for DemoSensorSettings class, a serializable entity that holds the configurations
//  for the DemoSensor process.  The various attributes are:
//
//		Server Name - the name of the CORBA server
//
//	    Command Complete Event Settings - the name and type of event to send when completing an
//		command asynchronously
//
//		GPS Event Settings - the name and type of the event to expect for GPS notifications (use
//		EventLib's GPSSampleEvent to unpack the fields of the message)
//
//		System Shutdown Event Settings - the name and type of the event to expect when being
//		notified of an imminent system shutdown
//
//		Telemetry Event Changed Event Settings - the name and type of the event to send when
//		notifying boundary servers that the number of samples to aggregate into a single report
//		or the retention time has changed (use EventLib's TelemtrySettingsChangedEvent to pack
//		up the event)
//
//		EventTransceiver Settings - initialization information for EventTransceiver, which allows
//		CORBA events to be received or transmitted
//
//		PayloadManagerClient Settings - initialization information for PayloadManagerClient, which
//		registers this process with PayloadManager (server name, board address, description, etc.)
//		and makes information for other servers accessible
//
//		Power On and Power Off verbs - the shell commands to run to turn the power on or off to the
//		sensor
//
//		SerialListener settings - the settings for the SerialListener class, which listens for
//		data from the serial port
//
//		SerialPort settings - the settings for the SerialPort class (name, baud rate, etc.), which
//		enables the program to interact with the serial port
// </summary>
//
// <owner>Mike Cookson</owner>
//------------------------------------------------------------------------------------------------

#ifndef __DEMOSENSORSETTINGS_H__
#define __DEMOSENSORSETTINGS_H__

#include "EventTransceiver.h"
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <string>
#include "EventSettings.h"
#include "PayloadManagerClientSettings.h"
#include "LqrSMACSerialListenerSettings.h"
#include "LqrSMACSerialPortSettings.h"

/*! \class DemoSensorSettings
 *  \brief Serializable entity class that holds settings for DemoSensor program
 */

class DemoSensorSettings
{
public:

	typedef LiquidRobotics::EventLib::EventSettings EventSettings;
	typedef LiquidRobotics::EventLib::EventTransceiver::Settings EventTransceiverSettings;
	typedef LiquidRobotics::EventLib::PayloadManagerClientSettings PayloadManagerClientSettings;
	typedef LiquidRobotics::SMACFramework::SerialListenerSettings SerialListenerSettings;
	typedef LiquidRobotics::SMACFramework::SerialPortSettings SerialPortSettings;
	typedef std::string string;

	/*! \brief Class constructor for DemoSensorSettings
	 */
	DemoSensorSettings();

	/*! \brief Reads the settings from the given named file (using boost XML serialization)
	 *  \sa load(), Save()
	 */
	void Load(
			const string& fileName			/**< [in] The file from which to load the settings */
			);


	/*! \brief Saves the settings to the given named file (using boost XML serialization)
	 *  \sa save(), Load()
	 */
	void Save(
			const string& fileName			/**< [in] The file to which to save the settings */
			) const;

	//------------//
	//- Entities -//
	//------------//

	/*! \brief Reads the "server name" property (used to register with CORBA)
	 *  \return The name of the server to register with CORBA
	 */
	const string& GetServerName() const;

	/*! \brief Sets the "server name" property (used to register with CORBA)
	 */
	void SetServerName(const string& newValue);

	/*! \brief Reads the event settings for the "command complete" CORBA event.
	 *  \return Event settings associated with the "command complete" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "Command Complete" announces completion
	 *  of SendCommand invocation that throws a "WillCompleteAsynchronously"
	 *  exception.
	 */
	const EventSettings& GetCommandCompleteEventSettings() const;

	/*! \brief Sets the event settings for the "command complete" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "Command Complete" announces completion
	 *  of SendCommand invocation that throws a "WillCompleteAsynchronously"
	 *  exception.
	 */
	void SetCommandCompleteEventSettings(
			const EventSettings& newValue	/**< [in] The new settings for "command complete" CORBA event */
			);

	/*! \brief Reads the event settings for the "GPS sample" CORBA event.
	 *  \return Event settings associated with the "GPS sample" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "GPS sample" contains the data for one
	 *  GPS reading, which must include latitude, longitude and time, but
	 *  may contain other data associated with the report.
	 */
	const EventSettings& GetGPSEventSettings() const;

	/*! \brief Sets the event settings for the "GPS sample" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "GPS sample" contains the data for one
	 *  GPS reading, which must include latitude, longitude and time, but
	 *  may contain other data associated with the report.
	 */
	void SetGPSEventSettings(
			const EventSettings& newValue	/**< [in] The new settings for "GPS sample" CORBA event */
			);

	/*! \brief Reads the event settings for the "system shutdown" CORBA event.
	 *  \return Event settings associated with the "system shutdown" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "System shutdown" is announced typically
	 *  when the navigation computer is about to cut power to the payload port.
	 *  It gives the program a chance to gracefully close files and otherwise
	 *  prepare.
	 */
	const EventSettings& GetSystemShutdownEventSettings() const;

	/*! \brief Sets the event settings for the "system shutdown" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "System shutdown" is announced typically
	 *  when the navigation computer is about to cut power to the payload port.
	 *  It gives the program a chance to gracefully close files and otherwise
	 *  prepare.
	 */
	void SetSystemShutdownEventSettings(
			const EventSettings& newValue	/**< [in] The new settings for "system shutdown" CORBA event */
			);

	/*! \brief Reads the event settings for the "telemetry changed" CORBA event.
	 *  \return Event settings associated with the "telemetry changed" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "Telemetry changed" announces to any boundary
	 *  interfaces that the parameters for a telemetry report are being
	 *  reconfigured (number of samples to accumulate, max retention time.)
	 */
	const EventSettings& GetTelemetryChangedEventSettings() const;

	/*! \brief Sets the event settings for the "telemetry changed" CORBA event.
	 *
	 *  The program uses these specific settings to configure the EventTransceiver
	 *  to call a specific member function when the event is received or to
	 *  configure outgoing events.  "Telemetry changed" announces to any boundary
	 *  interfaces that the parameters for a telemetry report are being
	 *  reconfigured (number of samples to accumulate, max retention time.)
	 */
	void SetTelemetryChangedEventSettings(
			const EventSettings& newValue	/**< [in] The new settings for "telemetry changed" CORBA event */
			);

	/*! \brief Returns the settings for EventTransceiver
	 *  \return The settings for EventTransceiver
	 *
	 *  EventTransciever distributes and receives CORBA events; the settings are
	 *  needed to instantiate and initialize the class instance.
	 */
	const EventTransceiverSettings& GetEventTransceiverSettings() const;

	/*! \brief Sets the settings for EventTransceiver
	 *
	 *  EventTransciever distributes and receives CORBA events; the settings are
	 *  needed to instantiate and initialize the class instance.
	 */
	void SetEventTransceiverSettings(
			const EventTransceiverSettings& newValue	/**< [in] The new settings EventTransceiver */
			);

	/*! \brief Returns the settings for PayloadManagerClient
	 *  \return The settings for PayloadManagerClient
	 *
	 *  PayloadManagerClient is the interface to PayloadManager.  All sensors
	 *  register with PayloadManager and provide some information about how to
	 *  be contacted and other process metadata.  The settings are needed to
	 *  instantiated and initialize PayloadManagerClient.
	 */
	const PayloadManagerClientSettings& GetPayloadManagerClientSettings() const;

	/*! \brief Sets the settings for PayloadManagerClient
	 *
	 *  PayloadManagerClient is the interface to PayloadManager.  All sensors
	 *  register with PayloadManager and provide some information about how to
	 *  be contacted and other process metadata.  The settings are needed to
	 *  instantiated and initialize PayloadManagerClient.
	 */
	void SetPayloadManagerClientSettings(
			const PayloadManagerClientSettings& newValue	/**< [in] The new settings for PayloadManager */
			);

	/*! \brief Returns the shell command to execute to turn off power to the sensor.
	 *  \return The shell command to execute to turn off power to the sensor.
	 *
	 *  This can be left blank if the program does not have a way to control
	 *  sensor power.
	 */
	const string& GetPowerOffVerb() const;

	/*! \brief Sets the shell command to execute to turn off power to the sensor.
	 *
	 *  This can be left blank if the program does not have a way to control
	 *  sensor power.
	 */
	void SetPowerOffVerb(
			const string& newValue	/**< [in] The new shell command that turns off power to the sensor (blank=not available) */
			);

	/*! \brief Returns the shell command to execute to turn on power to the sensor.
	 *  \return The shell command to execute to turn on power to the sensor.
	 *
	 *  This can be left blank if the program does not have a way to control
	 *  sensor power.
	 */
	const string& GetPowerOnVerb() const;

	/*! \brief Sets the shell command to execute to turn on power to the sensor.
	 *
	 *  This can be left blank if the program does not have a way to control
	 *  sensor power.
	 */
	void SetPowerOnVerb(
			const string& newValue	/**< [in] The new shell command that turns on power to the sensor (blank=not available) */
			);

	/*! \brief Returns settings for an instance of SerialListener
	 *  \return Settings for an instance of SerialListener
	 *
	 *  SerialListener is a class that listens to input from an ISerialPort and
	 *  returns the inputs as Boost events.  The settings are needed to instantiate
	 *  and initialize SerialListener.
	 */
	const SerialListenerSettings& GetSerialListenerSettings() const;

	/*! \brief Sets the settings for an instance of SerialListener
	 *
	 *  SerialListener is a class that listens to input from an ISerialPort and
	 *  returns the inputs as Boost events.  The settings are needed to instantiate
	 *  and initialize SerialListener.
	 */
	void SetSerialListenerSettings(
			const SerialListenerSettings& newValue	/**< [in] The new settings for SerialListener */
			);

	/*! \brief Returns settings for an instance of SerialPort
	 *  \return Settings for an instance of SerialPort
	 *
	 *  SerialPort is the SMAC Framework's interface to a serial port, with methods
	 *  to read or write data and configure its operation.  The settings contain
	 *  things like the port name, baud rate, data bits, stop bits, parity, etc.;
	 *  they are needed to instantiate and initialize SerialPort.
	 */
	const SerialPortSettings& GetSerialPortSettings() const;

	/*! \brief Sets the settings for an instance of SerialPort
	 *  \return Settings for an instance of SerialPort
	 *
	 *  SerialPort is the SMAC Framework's interface to a serial port, with methods
	 *  to read or write data and configure its operation.  The settings contain
	 *  things like the port name, baud rate, data bits, stop bits, parity, etc.;
	 *  they are needed to instantiate and initialize SerialPort.
	 */
	void SetSerialPortSettings(
			const SerialPortSettings& newValue	/**< [in] The new settings for a SerialPort */
			);

private:

	friend class boost::serialization::access;

	/*! \brief Boost Serialization method to load entities from an Archive
	 *  \sa Load(), Save(), save(), BOOST_SERIALIZATION_SPLIT_MEMBER(), BOOST_CLASS_VERSION()
	 *
	 *  This function can work with different types of Boost serialization
	 *  archive classes, but is meant to work with the XML version.  Splitting
	 *  the serialization methods into "load" and "save" allows the class
	 *  to read data stored by earlier versions of the program (by checking
	 *  the version number and responding appropriately.)
	 */
	template<class Archive>
	void load(
			Archive & ar,					/**< [in] The archive from which entities should be read */
			const unsigned int version	/**< [in] The version of data being read */
			)
	{
		ar & BOOST_SERIALIZATION_NVP(serverName);
		ar & BOOST_SERIALIZATION_NVP(commandCompleteEventSettings);
		ar & BOOST_SERIALIZATION_NVP(gpsEventSettings);
		ar & BOOST_SERIALIZATION_NVP(telemetryChangedEventSettings);
		ar & BOOST_SERIALIZATION_NVP(eventTransceiverSettings);
		ar & BOOST_SERIALIZATION_NVP(payloadManagerClientSettings);

		if (version >= 2)
		{
			ar & BOOST_SERIALIZATION_NVP(systemShutdownEventSettings);
			ar & BOOST_SERIALIZATION_NVP(powerOffVerb);
			ar & BOOST_SERIALIZATION_NVP(powerOnVerb);
			ar & BOOST_SERIALIZATION_NVP(serialListenerSettings);
			ar & BOOST_SERIALIZATION_NVP(serialPortSettings);
		}
	}

	/*! \brief Boost Serialization method to load entities from an Archive
	 *  \sa Load(), Save(), load()
	 *
	 *  This function can work with different types of Boost serialization
	 *  archive classes, but is meant to work with the XML version.
	 */
	template<class Archive>
	void save(Archive & ar, const unsigned int version) const
	{
		ar & BOOST_SERIALIZATION_NVP(serverName);
		ar & BOOST_SERIALIZATION_NVP(commandCompleteEventSettings);
		ar & BOOST_SERIALIZATION_NVP(gpsEventSettings);
		ar & BOOST_SERIALIZATION_NVP(telemetryChangedEventSettings);
		ar & BOOST_SERIALIZATION_NVP(eventTransceiverSettings);
		ar & BOOST_SERIALIZATION_NVP(payloadManagerClientSettings);
		ar & BOOST_SERIALIZATION_NVP(systemShutdownEventSettings);
		ar & BOOST_SERIALIZATION_NVP(powerOffVerb);
		ar & BOOST_SERIALIZATION_NVP(powerOnVerb);
		ar & BOOST_SERIALIZATION_NVP(serialListenerSettings);
		ar & BOOST_SERIALIZATION_NVP(serialPortSettings);
	}

	BOOST_SERIALIZATION_SPLIT_MEMBER()

	string serverName;												//!< Name of the CORBA server
	EventSettings commandCompleteEventSettings;						//!< Name and type of the CORBA event to send when completing a command asynchronously (use EventLib's SendCommandCompleteEvent to encode)
	EventSettings gpsEventSettings;									//!< Name and type of the CORBA event to expect for GPS notification (use EventLib's GPSSampleEvent to decode)
	EventSettings telemetryChangedEventSettings;					//!< Name and type of the CORBA event to send when changing the boundary interfaces data aggregation and retention policies (use EventLib's TelemetrySettingsChangedEvent to encode)
	EventSettings systemShutdownEventSettings;						//!< Name and type of the CORBA event to expect when being notified of an imminent system shutdown
	EventTransceiverSettings eventTransceiverSettings;				//!< Settings for EventTransceiver, which allows CORBA events to be sent and received
	PayloadManagerClientSettings payloadManagerClientSettings;		//!< Settings for PayloadManagerClient, which registers server attributes of this process with PayloadManager and gives access to the registry
	string powerOffVerb;											//!< System command to power the sensor off (blank for no command)
	string powerOnVerb;												//!< System command to power the sensor on (blank for no command)
	SerialListenerSettings serialListenerSettings;					//!< Settings for an instance of SerialListener, which waits for serial port data and fires incoming data via boost signals
	SerialPortSettings serialPortSettings;							//!< Settings (name, baud rate, etc) for an instance of SerialPort, which is a boundary interface for serial ports
};

BOOST_CLASS_VERSION(DemoSensorSettings, 2)

#endif
