//---------------------------------------------------------------------------------------------
// <copyright file="LqrSMACIObjectBroker.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 the IObjectBroker class, an abstract base class that provides a simplified
//  CORBA interface.
// </summary>
//
// <owner>Mike Cookson</owner>
//---------------------------------------------------------------------------------------------

#ifndef __IOBJECTBROKER_H__
#define __IOBJECTBROKER_H__

#include "omniORB4/CORBA.h"
#include "LqrSMACDeclareException.h"
#include <set>
#include <stdexcept>
#include <string>
#include <vector>
#include <omniORB4/CORBA.h>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>

namespace LiquidRobotics {
namespace SMACFramework {

class IObjectBroker
{
public:

	DECLARE_EXCEPTION(AlreadyInitialized, std::logic_error);
	DECLARE_EXCEPTION(NotInitialized, std::logic_error);
	DECLARE_EXCEPTION(NarrowFailure, std::runtime_error);
	DECLARE_EXCEPTION(NotInitializedAsClient, std::logic_error);
	DECLARE_EXCEPTION(NotInitializedAsServer, std::logic_error);
	DECLARE_EXCEPTION(ShutDown, std::logic_error);

	typedef CORBA::Any Any;
	typedef CORBA::Any_var Any_var;
	typedef CORBA::Object_ptr Object_ptr;
	typedef CORBA::Object_var Object_var;
	typedef CORBA::ORB_var ORB_var;
	typedef boost::shared_ptr<IObjectBroker> Ptr;
	typedef std::string string;
	typedef CORBA::TypeCode_ptr TypeCode_ptr;
	typedef CORBA::TypeCode_var TypeCode_var;
	typedef std::vector<string> StringVector;
	typedef std::pair<string,string> StringPair;
	typedef std::vector<StringPair> StringPairVector;
	typedef std::set<StringPairVector> StringPairVectorSet;
	typedef boost::signals2::signal<void (IObjectBroker& sender)> ShutdownSignalType;

	IObjectBroker() { }
	virtual ~IObjectBroker() { }

	virtual Object_var ActivateInstance(PortableServer::Servant pServant) = 0;
	virtual Object_var AdvertizeInstance(PortableServer::Servant pServant, const char* instanceName, const char* instanceKind = NULL) = 0;
	virtual void DeactivateAll() = 0;
	virtual void DeactivateInstance(PortableServer::Servant pServant) = 0;
	virtual bool GetAdvertizedInstanceNameFromStringizedName(const char* instanceStringized, string& advertizedInstanceName, string& advertizedInstanceKind) const = 0;
	virtual Object_var GetRawDynamicObjectFromTypeCode(TypeCode_ptr typeCode) = 0;
	virtual Object_var GetRawObjectFromStringizedName(const char* instanceStringized) = 0;
	virtual Object_var GetRawRootInstance(const char* instanceName) = 0;
	virtual Object_var GetRawNamedInstance(const char* instanceName, const char* instanceKind = NULL, bool validateName = true, StringPairVectorSet* cachePtr = NULL) = 0;
	virtual void GetServers(StringPairVectorSet& servers) = 0;
	virtual string GetStringizedReference(CORBA::Object_ptr pRef) = 0;
	virtual void Initialize(int& argc, char**& argv) = 0;
	virtual bool IsShutdownQueued() = 0;
	virtual bool IsShutDown() = 0;
	virtual void ListenForRequests() = 0;
	virtual void QueueShutdown() = 0;
	virtual void Shutdown(bool waitForCompletion = true) = 0;
	virtual void UnadvertiseAll() = 0;
	virtual void UnadvertiseInstance(const char* instanceName, const char* instanceKind = NULL) = 0;
	virtual bool ValidateNamedInstance(const char* instanceName, const char* instanceKind, StringPairVectorSet* cachePtr = NULL, bool throwOnFailure = true) = 0;

	virtual void AnyToStringVector(StringVector& to, const Any& from) = 0;
	virtual Any_var StringVectorToAny(const StringVector& from) = 0;
	virtual Any_var StringVectorToAny(const string* pStart, size_t numElems) = 0;

	template<typename VECTOR_TYPE>
	void AnyToCppVector(VECTOR_TYPE& to, const Any& from);
	template<typename VECTOR_TYPE, typename COPIER>				// COPIER constructor(const Any& from, T& to)
	void AnyToCppVector(VECTOR_TYPE& to, const Any& from);

	template<typename VECTOR_TYPE>
	Any_var CppVectorToAny(const VECTOR_TYPE& from, TypeCode_ptr resultType);
	template<typename VECTOR_TYPE, class COPIER>				// COPIER constructor(DynAnySeq& to, _CORBA_ULong idx, const uint8_t& from)
	Any_var CppVectorToAny(const VECTOR_TYPE& from, TypeCode_ptr resultType);
	template<typename CPP_TYPE>
	Any_var CppVectorToAny(const CPP_TYPE* from, size_t numElems, TypeCode_ptr resultType);
	template<typename CPP_TYPE, class COPIER>					// COPIER constructor(DynAnySeq& to, _CORBA_ULong idx, const uint8_t& from)
	Any_var CppVectorToAny(const CPP_TYPE* from, size_t numElems, TypeCode_ptr resultType);

	template<typename RETURN_TYPE, typename NARROWING_TYPE>
	RETURN_TYPE GetDynamicObjectFromTypeCode(TypeCode_ptr typeCode);

	template<typename RETURN_TYPE, typename NARROWING_TYPE>
	RETURN_TYPE GetObjectFromStringizedName(const char* instanceStringized);

	template<typename RETURN_TYPE, typename NARROWING_TYPE>
	RETURN_TYPE GetRootInstance(const char* instanceName);

	template<typename RETURN_TYPE, typename NARROWING_TYPE>
	RETURN_TYPE GetNamedInstance(const char* instanceName, const char* instanceKind = NULL, bool validateName = true, StringPairVectorSet* cachePtr = NULL);

	ShutdownSignalType ShutdownSignal;

protected:

	virtual ORB_var ORB() = 0;
};

}
}

#endif
