//------------------------------------------------------------------------------
// <copyright file="EventTransceiver_Settings.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 EventTransceiver's Settings class
// </summary>
//
// <owner>Mike Cookson</owner>
//------------------------------------------------------------------------------

#ifndef __EVENTLIB_EVENTTRANSCIEVERSETTINGS_H__
#define __EVENTLIB_EVENTTRANSCIEVERSETTINGS_H__

#include "EventBase.h"
#include "LqrSMACSharedLib.h"
#include <string>
#include <map>
#include <set>
#include <boost/serialization/access.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/split_member.hpp>

namespace LiquidRobotics {

namespace SMAC {
	class EventManagerCustomFilter;
}

namespace EventLib {

class EventTransceiver;

class SHARED_LIB_PUBLIC EventTransceiverSettings
{
public:

	typedef std::set<EventType> EventTypeSet;
	typedef std::string string;
	typedef std::set<string> StringSet;
	typedef LiquidRobotics::SMAC::EventManagerCustomFilter EventManagerCustomFilter;

	EventTransceiverSettings();
	EventTransceiverSettings(const EventTransceiverSettings& other);

	EventTransceiverSettings& operator=(const EventTransceiverSettings& other);
	bool operator==(const EventTransceiverSettings& other) const;

	const string& GetEventServiceName() const			{ return eventServiceName; }
	void SetEventServiceName(const string& newValue)	{ eventServiceName = newValue; }

	const string& GetEventServiceKind() const			{ return eventServiceKind; }
	void SetEventServiceKind(const string& newValue)	{ eventServiceKind = newValue; }

	bool GetReceiveEnable() const						{ return receiveEnable; }
	void SetReceiveEnable(bool newValue)				{ receiveEnable = newValue; }

	const StringSet& GetEventNameFilter() const;
	void SetEventNameFilter(const StringSet& newValue);

	const EventTypeSet& GetEventTypeFilter() const;
	void SetEventTypeFilter(const EventTypeSet& newValue);

	bool HaveEventForAlias(const string& aliasName) const;
	string EventForAlias(const string& aliasName) const;
	void RemoveAliasForEvent(const string& aliasName);
	void RemoveAllAliasesForEvents();
	void SetAliasForEvent(const string& aliasName, const string& eventName);
	void DescribeAliasList(std::ostream& stm) const;

	bool HaveAliasForEvent(const string& eventName) const;
	string AliasForEvent(const string& eventName) const;
	void RemoveEventForAlias(const string& eventName);

	void ClearEventFilter();
	bool EventFilterEnabled() const;
	void SetEventFilterEnabled(bool enabled = true);
	bool EventNameEnabled(const string& eventName) const;
	void EnableEventName(const string& eventName, bool enabled = true);
	bool EventTypeEnabled(const EventType& eventType) const;
	void EnableEventType(const EventType& eventType, bool enabled = true);
	void DescribeEventFilter(std::ostream& stm) const;

	bool DisplayReceivedEvents() const;
	void DisplayReceivedEvents(bool newValue);
	bool FullyDescribeReceivedEvents() const;
	void FullyDescribeReceivedEvents(bool newValue);
	const StringSet& DoNotDisplayList() const;
	void DoNotDisplayList(const StringSet& newValue);

	void GetCustomFilter(EventManagerCustomFilter& cf) const;
	void SetCustomFilter(const EventManagerCustomFilter& cf);

	void Load(const string& fileName);
	void Save(const string& fileName) const;

private:

	typedef std::map<string,string> StringMap;

	friend class boost::serialization::access;

	template<class Archive>
	void save(Archive & ar, const unsigned int version) const
	{
		// first versions
		ar & BOOST_SERIALIZATION_NVP(eventServiceName);
		ar & BOOST_SERIALIZATION_NVP(eventServiceKind);
		ar & BOOST_SERIALIZATION_NVP(receiveEnable);
		ar & BOOST_SERIALIZATION_NVP(aliasToEvent);
		//SynchronizeEventToAlias();
		ar & BOOST_SERIALIZATION_NVP(eventFilterEnabled);
		ar & BOOST_SERIALIZATION_NVP(eventNameFilter);
		ar & BOOST_SERIALIZATION_NVP(eventTypeFilter);

		// starting in version 2
		ar & BOOST_SERIALIZATION_NVP(displayReceivedEvents)
		   & BOOST_SERIALIZATION_NVP(fullyDescribeReceivedEvents)
		   & BOOST_SERIALIZATION_NVP(doNotDisplayList);
	}

	template<class Archive>
    void load(Archive & ar, const unsigned int version)
	{
		ar & BOOST_SERIALIZATION_NVP(eventServiceName);
		ar & BOOST_SERIALIZATION_NVP(eventServiceKind);
		ar & BOOST_SERIALIZATION_NVP(receiveEnable);
		ar & BOOST_SERIALIZATION_NVP(aliasToEvent);
		SynchronizeEventToAlias();
		ar & BOOST_SERIALIZATION_NVP(eventFilterEnabled);
		ar & BOOST_SERIALIZATION_NVP(eventNameFilter);
		ar & BOOST_SERIALIZATION_NVP(eventTypeFilter);

		if (version == 2)
			ar & BOOST_SERIALIZATION_NVP(displayReceivedEvents)
		       & BOOST_SERIALIZATION_NVP(fullyDescribeReceivedEvents)
			   & BOOST_SERIALIZATION_NVP(doNotDisplayList);
		else
		{
			displayReceivedEvents = fullyDescribeReceivedEvents = true;
			doNotDisplayList.clear();
		}
	}

	BOOST_SERIALIZATION_SPLIT_MEMBER()

	void SynchronizeEventToAlias();
	static bool Equal(const StringMap& m1, const StringMap& m2);
	static bool Equal(const StringSet& s1, const StringSet& s2);
	static bool Equal(const EventTypeSet& s1, const EventTypeSet& s2);

	string eventServiceName;
	string eventServiceKind;
	bool receiveEnable;
	StringMap aliasToEvent;
	StringMap eventToAlias;
	bool eventFilterEnabled;
	StringSet eventNameFilter;
	EventTypeSet eventTypeFilter;
	bool displayReceivedEvents;
	bool fullyDescribeReceivedEvents;
	StringSet doNotDisplayList;
};

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

}
}

BOOST_CLASS_VERSION(LiquidRobotics::EventLib::EventTransceiverSettings, 2)


#endif
