//--------------------------------------------------------------------------------
// <copyright file="PayloadInterfaceController_Config.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>
// 	Declaration of settings for the PayloadInterface class
// </summary>
//
// <owner>Mike Cookson</owner>
//--------------------------------------------------------------------------------

#ifndef PAYLOADINTERFACECONTROLLER_CONFIG_H_
#define PAYLOADINTERFACECONTROLLER_CONFIG_H_

#include "EventSettings.h"
#include "EventTransceiver_Settings.h"
#include "LqrSMACSharedLib.h"
#include "PayloadManagerClientSettings.h"
#include "PayloadMessage.h"
#include <boost/serialization/access.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/version.hpp>
#include <list>
#include <string>
#include <utility>

namespace LiquidRobotics {
namespace PayloadInterface {

class SHARED_LIB_PUBLIC PayloadInterfaceController_Config
{
public:

	typedef LiquidRobotics::EventLib::EventSettings EventSettings;
	typedef LiquidRobotics::EventLib::EventTransceiverSettings EventTransceiverSettings;
	typedef std::pair<EventSettings, PayloadMessage::BoardAddress> EventAndDestination;
	typedef std::list<EventAndDestination> EventAndDestinationList;
	typedef LiquidRobotics::EventLib::PayloadManagerClientSettings PayloadManagerClientSettings;
	typedef std::string string;
	typedef std::list<string> StringList;

	struct SetParamInfo
	{
		SetParamInfo()
		: paramID(0)
		{
		}

		SetParamInfo(uint16_t id, const string& name, const string& typ)
		: paramID(id)
		, paramType(typ)
		{
			paramNames.push_back(name);
		}

		SetParamInfo(uint16_t id, const string& name, const string& name2, const string& typ)
		: paramID(id)
		, paramType(typ)
		{
			paramNames.push_back(name);
			paramNames.push_back(name2);
		}

		uint16_t paramID;
		StringList paramNames;
		string paramType;

		friend class boost::serialization::access;

		template<class Archive>
		void load(Archive & ar, const unsigned int version)
		{
			ar & BOOST_SERIALIZATION_NVP(paramID);						// 1
			ar & BOOST_SERIALIZATION_NVP(paramNames);					// 1
			ar & BOOST_SERIALIZATION_NVP(paramType);					// 1
		}

		template<class Archive>
		void save(Archive & ar, const unsigned int version) const
		{
			ar & BOOST_SERIALIZATION_NVP(paramID);						// 1
			ar & BOOST_SERIALIZATION_NVP(paramNames);					// 1
			ar & BOOST_SERIALIZATION_NVP(paramType);					// 1
		}

		BOOST_SERIALIZATION_SPLIT_MEMBER()
	};

	typedef std::list<SetParamInfo> SetParamInfoList;

	PayloadInterfaceController_Config();
	virtual ~PayloadInterfaceController_Config() { }

	const string& GetDescription() const							{ return description; }
	void SetDescription(const string& newValue)						{ description = newValue; }

	uint16_t GetDeviceType() const									{ return deviceType; }
	string GetSerialNum() const										{ return serialNum; }
	uint32_t GetPollingRate() const									{ return pollingRate; }
	bool GetTelemetryRequested() const								{ return wantTelemetry; }
	bool GetPowerNotificationRequested() const						{ return wantPowerNotification; }
	bool GetEventsRequested() const									{ return wantEvents; }
	bool GetEchoedAcksRequested() const								{ return wantEchoedAcks; }
	uint8_t GetFirmwareMajor() const								{ return firmwareMajor; }
	uint8_t GetFirmwareMinor() const								{ return firmwareMinor; }
	uint16_t GetFirmwareRev() const									{ return firmwareRev; }

	const StringList& GetDemoServerList() const						{ return demoServerList; }

	const string& GetShutdownVerb() const							{ return shutdownVerb; }
	const uint8_t GetPowerOffDelay() const							{ return powerOffDelay; }
	const uint8_t GetPowerOnDelay() const							{ return powerOnDelay; }
	const string& GetDateVerb() const								{ return dateVerb; }

	string GetDateVerbGMT(int year, int month, int day, int hour, int minute, int second) const;

	const EventSettings& GetShutdownEventSettings() const;
	void SetShutdownEventSettings(const EventSettings& newValue);

	unsigned GetShutdownDelay() const;
	void SetShutdownDelay(unsigned newValue);

	const EventSettings& GetAddressedMessageEventSettings() const;
	void SetAddressedMessageEventSettings(const EventSettings& newValue);

	const EventSettings& GetAlarmReportEventSettings() const;
	void SetAlarmReportEventSettings(const EventSettings& newValue);

	const EventSettings& GetFCCIncomingMessageEventSettings() const;
	void SetFCCIncomingMessageEventSettings(const EventSettings& newValue);

	const EventSettings& GetFCCOutgoingMessageEventSettings() const;
	void SetFCCOutgoingMessageEventSettings(const EventSettings& newValue);

	const EventSettings& GetCommandCompleteEventSettings() const;
	void SetCommandCompleteEventSettings(const EventSettings& newValue);

	const EventSettings& GetGpsSampleEventSettings() const;
	void SetGpsSampleEventSettings(const EventSettings& newValue);

	const EventAndDestinationList& GetNewFileAvailableEventSettings() const;
	void SetNewFileAvailableEventSettings(const EventAndDestinationList& newValue);

	const EventSettings& GetTelemetryChangedEventSettings() const;
	void SetTelemetryChangedEventSettings(const EventSettings& newValue);

	const EventSettings& GetSystemGPSOfflineSettings() const;
	void SetSystemGPSOfflineSettings(const EventSettings& newValue);

	const EventSettings& GetSystemGPSOnlineSettings() const;
	void SetSystemGPSOnlineSettings(const EventSettings& newValue);

	const EventSettings& GetHostGPSEventSettings() const;
	void SetHostGPSEventSettings(const EventSettings& newValue);

	const EventTransceiverSettings& GetEventTransceiverSettings() const;
	void SetEventTransceiverSettings(const EventTransceiverSettings& newValue);

	const PayloadManagerClientSettings& GetPayloadManagerClientSettings() const;
	void SetPayloadManagerClientSettings(const PayloadManagerClientSettings& newValue);

	size_t GetMaxCommandOutput() const;
	void SetMaxCommandOutput(size_t newValue);

	string GetTarProcessingCommand() const;
	void SetTarProcessingCommand(const string& newValue);

	unsigned GetMaxConsoleOutputBlocks() const;
	void SetMaxConsoleOutputBlocks(unsigned newValue);

	bool GetDistributeGPS() const									{ return distributeGPS; }
	void SetDistributeGPS(const bool newValue);

	const SetParamInfoList& GetSetParamInfoList() const;

	bool GetEnableNakWithDescription() const 							{ return enableNakWithDescription; }

private:

	friend class boost::serialization::access;

	template<class Archive>
	void load(Archive & ar, const unsigned int version)
	{
		if ((version >= 1) && (version <= 2))
		{
			PayloadMessage::BoardID boardID;
			PayloadMessage::BoardAddress boardAddress;
			ar & BOOST_SERIALIZATION_NVP(boardID);						// 1-2
			ar & BOOST_SERIALIZATION_NVP(boardAddress);					// 1-2
		}

		ar & BOOST_SERIALIZATION_NVP(description);					// 1
		ar & BOOST_SERIALIZATION_NVP(deviceType);					// 1
		ar & BOOST_SERIALIZATION_NVP(serialNum);					// 1
		ar & BOOST_SERIALIZATION_NVP(pollingRate);					// 1
		ar & BOOST_SERIALIZATION_NVP(wantTelemetry);				// 1
		ar & BOOST_SERIALIZATION_NVP(wantPowerNotification);		// 1
		ar & BOOST_SERIALIZATION_NVP(wantEvents);					// 1
		ar & BOOST_SERIALIZATION_NVP(wantEchoedAcks);				// 1
		ar & BOOST_SERIALIZATION_NVP(firmwareMajor);				// 1
		ar & BOOST_SERIALIZATION_NVP(firmwareMinor);				// 1
		ar & BOOST_SERIALIZATION_NVP(firmwareRev);					// 1
		ar & BOOST_SERIALIZATION_NVP(demoServerList);				// 1
		ar & BOOST_SERIALIZATION_NVP(shutdownVerb);					// 1
		ar & BOOST_SERIALIZATION_NVP(powerOffDelay);				// 1
		ar & BOOST_SERIALIZATION_NVP(powerOnDelay);					// 1
		ar & BOOST_SERIALIZATION_NVP(dateVerb);						// 1
		ar & BOOST_SERIALIZATION_NVP(shutdownEvent);				// 1
		ar & BOOST_SERIALIZATION_NVP(shutdownDelay);				// 1
		ar & BOOST_SERIALIZATION_NVP(FCCIncomingMessageEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(FCCOutgoingMessageEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(commandCompleteEvent);			// 1
		ar & BOOST_SERIALIZATION_NVP(gpsSampleEvent);				// 1
		ar & BOOST_SERIALIZATION_NVP(newFileAvailableEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(telemetryChangedEvent);		// 1

		if (version >= 2)
			ar & BOOST_SERIALIZATION_NVP(addressableMessageEvent);	// 2

		if (version >= 6)
			ar & BOOST_SERIALIZATION_NVP(alarmReportEvent);			// 6

		if (version >= 5) {
			ar & BOOST_SERIALIZATION_NVP(systemGPSOfflineEvent);	// 5
			ar & BOOST_SERIALIZATION_NVP(systemGPSOnlineEvent);		// 5
			ar & BOOST_SERIALIZATION_NVP(hostGPSEvent);				// 5
		}

		ar & BOOST_SERIALIZATION_NVP(maxCommandOutput);				// 1
		ar & BOOST_SERIALIZATION_NVP(tarProcessingCommand);			// 1
		ar & BOOST_SERIALIZATION_NVP(maxConsoleOutputBlocks);		// 1
		ar & BOOST_SERIALIZATION_NVP(etSettings);					// 1
		ar & BOOST_SERIALIZATION_NVP(pmSettings);					// 1
		ar & BOOST_SERIALIZATION_NVP(distributeGPS);				// 1

		if (version >= 4)
			ar & BOOST_SERIALIZATION_NVP(setParamInfoList);			// 4

		if (version >= 7)
			ar & BOOST_SERIALIZATION_NVP(enableNakWithDescription);	// 7
	}

	template<class Archive>
	void save(Archive & ar, const unsigned int version) const
	{
		ar & BOOST_SERIALIZATION_NVP(description);					// 1
		ar & BOOST_SERIALIZATION_NVP(deviceType);					// 1
		ar & BOOST_SERIALIZATION_NVP(serialNum);					// 1
		ar & BOOST_SERIALIZATION_NVP(pollingRate);					// 1
		ar & BOOST_SERIALIZATION_NVP(wantTelemetry);				// 1
		ar & BOOST_SERIALIZATION_NVP(wantPowerNotification);		// 1
		ar & BOOST_SERIALIZATION_NVP(wantEvents);					// 1
		ar & BOOST_SERIALIZATION_NVP(wantEchoedAcks);				// 1
		ar & BOOST_SERIALIZATION_NVP(firmwareMajor);				// 1
		ar & BOOST_SERIALIZATION_NVP(firmwareMinor);				// 1
		ar & BOOST_SERIALIZATION_NVP(firmwareRev);					// 1
		ar & BOOST_SERIALIZATION_NVP(demoServerList);				// 1
		ar & BOOST_SERIALIZATION_NVP(shutdownVerb);					// 1
		ar & BOOST_SERIALIZATION_NVP(powerOffDelay);				// 1
		ar & BOOST_SERIALIZATION_NVP(powerOnDelay);					// 1
		ar & BOOST_SERIALIZATION_NVP(dateVerb);						// 1
		ar & BOOST_SERIALIZATION_NVP(shutdownEvent);				// 1
		ar & BOOST_SERIALIZATION_NVP(shutdownDelay);				// 1
		ar & BOOST_SERIALIZATION_NVP(FCCIncomingMessageEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(FCCOutgoingMessageEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(commandCompleteEvent);			// 1
		ar & BOOST_SERIALIZATION_NVP(gpsSampleEvent);				// 1
		ar & BOOST_SERIALIZATION_NVP(newFileAvailableEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(telemetryChangedEvent);		// 1
		ar & BOOST_SERIALIZATION_NVP(addressableMessageEvent);		// 2
		ar & BOOST_SERIALIZATION_NVP(alarmReportEvent);				// 6
		ar & BOOST_SERIALIZATION_NVP(systemGPSOfflineEvent);		// 5
		ar & BOOST_SERIALIZATION_NVP(systemGPSOnlineEvent);			// 5
		ar & BOOST_SERIALIZATION_NVP(hostGPSEvent);					// 5
		ar & BOOST_SERIALIZATION_NVP(maxCommandOutput);				// 1
		ar & BOOST_SERIALIZATION_NVP(tarProcessingCommand);			// 1
		ar & BOOST_SERIALIZATION_NVP(maxConsoleOutputBlocks);		// 1
		ar & BOOST_SERIALIZATION_NVP(etSettings);					// 1
		ar & BOOST_SERIALIZATION_NVP(pmSettings);					// 1
		ar & BOOST_SERIALIZATION_NVP(distributeGPS);				// 1
		ar & BOOST_SERIALIZATION_NVP(setParamInfoList);				// 4
		ar & BOOST_SERIALIZATION_NVP(enableNakWithDescription);		// 7
	}

	BOOST_SERIALIZATION_SPLIT_MEMBER()

	// ID data
	string description;
	uint16_t deviceType;
	string serialNum;
	uint32_t pollingRate;
	bool wantTelemetry;
	bool wantPowerNotification;
	bool wantEvents;
	bool wantEchoedAcks;
	uint8_t firmwareMajor;
	uint8_t	firmwareMinor;
	uint16_t firmwareRev;
	StringList demoServerList;
	string shutdownVerb;
	uint8_t powerOffDelay;
	uint8_t powerOnDelay;
	string dateVerb;
	EventSettings shutdownEvent;
	unsigned shutdownDelay;
	EventSettings FCCIncomingMessageEvent;
	EventSettings FCCOutgoingMessageEvent;
	EventSettings commandCompleteEvent;
	EventSettings gpsSampleEvent;
	EventAndDestinationList newFileAvailableEvent;
	EventSettings telemetryChangedEvent;
	EventSettings addressableMessageEvent;
	EventSettings alarmReportEvent;
	EventSettings systemGPSOfflineEvent;
	EventSettings systemGPSOnlineEvent;
	EventSettings hostGPSEvent;

	size_t maxCommandOutput;
	string tarProcessingCommand;
	unsigned maxConsoleOutputBlocks;
	EventTransceiverSettings etSettings;
	PayloadManagerClientSettings pmSettings;
	bool distributeGPS;
	SetParamInfoList setParamInfoList;
	bool enableNakWithDescription;
};

SHARED_LIB_PUBLIC std::ostream& operator<<(std::ostream& stm, const PayloadInterfaceController_Config& settings);

}
}

BOOST_CLASS_VERSION(LiquidRobotics::PayloadInterface::PayloadInterfaceController_Config, 7)
BOOST_CLASS_VERSION(LiquidRobotics::PayloadInterface::PayloadInterfaceController_Config::SetParamInfo, 1)

#endif
