/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2008 OMC Denmark ApS.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "typesS_impl.h"
#include "obj_utils.h"
#include "conv_utils.h"

#include "templates.i"

// ******************************** //
// ***         IUnknown         *** //
// ******************************** //
BRUTUS_IUnknown_i::BRUTUS_IUnknown_i(LPUNKNOWN Unknown,
				     LPMAPISESSION MAPISession,
				     ::PortableServer::POA_ptr Poa)
	: unknown_(Unknown),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::BRESULT BRUTUS_IUnknown_i::QueryInterface(const char *iid,
						    ::BRUTUS::IUnknown_out ppvObject)
{
	ppvObject = ::BRUTUS::IUnknown::_nil();

	::GUID mapi_iid;
	if (!guid_brutus_to_mapi_no_alloc(iid, &mapi_iid)) {
		BRUTUS_LOG_BUG("Could not convert ::BRUTUS::GUID into MAPI GUID");
		return ::BRUTUS::BRUTUS_MAPI_E_INVALID_PARAMETER;
	}

	HRESULT hr;
	void *object = NULL;
	{
		ACE_Write_Guard<ACE_RW_Mutex> guard(mutex_);
		hr = unknown_->QueryInterface(mapi_iid, &object);
	}

	::BRUTUS::BRESULT br;
	if (!hresult_to_bresult(hr, br)) {
		BRUTUS_LOG_BUG("Could not convert HRESULT into BRESULT");
		return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
	}

	if (hr == S_OK) {
		if (!create_brutus_object(iid, (LPUNKNOWN)object, poa_, ppvObject, mapi_session_)) {
			BRUTUS_LOG_BUG("Could not create brutus object.");
			((LPUNKNOWN)object)->Release();
			return ::BRUTUS::BRUTUS_INTERNAL_ERROR;
		}
	}

	return br;
}

void BRUTUS_IUnknown_i::Destroy(::CORBA::ULong InstanceID)
{
	BRUTUS_LOG_INF("Entering BRUTUS_IUnknown_i::Destroy()");

	::PortableServer::ObjectId_var oid;
	oid = poa_->servant_to_id(this);

	poa_->deactivate_object(oid);

	BRUTUS_LOG_INF("Leaving BRUTUS_IUnknown_i::Destroy()");
}


// ********************************* //
// ***   SRestrictionContainer   *** //
// ********************************* //
BRUTUS_SRestrictionContainer_i::BRUTUS_SRestrictionContainer_i(::SRestriction *Res,
							       LPMAPISESSION MAPISession,
							       ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::SRestriction * BRUTUS_SRestrictionContainer_i::content(void)
{
	::BRUTUS::SRestriction_var retval;
	srestriction_mapi_to_brutus(res_, mapi_session_, retval.out(), poa_.in());

	return retval._retn();
}

void BRUTUS_SRestrictionContainer_i::Destroy(void)

{
	BRUTUS_LOG_INF("Entering BRUTUS_SRestrictionContainer_i::Destroy()");

	::PortableServer::POAManager_var poa_manager = poa_->the_POAManager();

	// makes sure that all objects are closed from the world
	poa_manager->deactivate(0, 0);

	// free the restriction structure
	MAPIFreeBuffer(res_);

	// initiate etherealization by calling _remove_ref() on
	// all objects in this poa, including *this* object.
	poa_->destroy(1, 0);

	BRUTUS_LOG_INF("Leaving BRUTUS_SRestrictionContainer_i::Destroy()");
}



// ********************************* //
// ***    SRestriction types     *** //
// ********************************* //
BRUTUS_SAndRestriction_i::BRUTUS_SAndRestriction_i(::SAndRestriction *Res,
						   LPMAPISESSION MAPISession,
						   ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::seq_SRestriction * BRUTUS_SAndRestriction_i::lpRes(void)

{
	::BRUTUS::seq_SRestriction_var retval;
	try {
		retval = new ::BRUTUS::seq_SRestriction;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		throw ::CORBA::NO_MEMORY();
	}
	retval->length(res_->cRes);

	::BRUTUS::SRestriction_var sres;
	for (unsigned long n = 0; n < res_->cRes; n++) {
		srestriction_mapi_to_brutus(&(res_->lpRes[n]), mapi_session_, sres.out(), poa_.in());
		retval[(::CORBA::ULong)n] = sres;
	}

	return retval._retn();
}


BRUTUS_SOrRestriction_i::BRUTUS_SOrRestriction_i(::SOrRestriction *Res,
						 LPMAPISESSION MAPISession,
						 ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::seq_SRestriction * BRUTUS_SOrRestriction_i::lpRes(void)

{
	::BRUTUS::seq_SRestriction_var retval;
	try {
		retval = new ::BRUTUS::seq_SRestriction;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		throw ::CORBA::NO_MEMORY();
	}
	retval->length(res_->cRes);

	::BRUTUS::SRestriction_var sres;
	for (unsigned long n = 0; n < res_->cRes; n++) {
		srestriction_mapi_to_brutus(&(res_->lpRes[n]), mapi_session_, sres.out(), poa_.in());
		retval[(::CORBA::ULong)n] = sres;
	}

	return retval._retn();
}


BRUTUS_SNotRestriction_i::BRUTUS_SNotRestriction_i(::SNotRestriction *Res,
						   LPMAPISESSION MAPISession,
						   ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::CORBA::ULong BRUTUS_SNotRestriction_i::ulReserved(void)

{
	return (::CORBA::ULong)res_->ulReserved;
}

void BRUTUS_SNotRestriction_i::ulReserved(::CORBA::ULong ulReserved)

{
	res_->ulReserved = (unsigned long)ulReserved;
}

::BRUTUS::SRestriction * BRUTUS_SNotRestriction_i::lpRes(void)

{
	::BRUTUS::SRestriction_var retval;
	srestriction_mapi_to_brutus(res_->lpRes, mapi_session_, retval.out(), poa_.in());

	return retval._retn();
}


BRUTUS_SContentRestriction_i::BRUTUS_SContentRestriction_i(::SContentRestriction *Res,
							   LPMAPISESSION MAPISession,
							   ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::FUZZY_TYPE BRUTUS_SContentRestriction_i::ulFuzzyLevel(void)

{
	::BRUTUS::FUZZY_TYPE retval = (::BRUTUS::FUZZY_TYPE)0;
	fuzzyLevel_mapi_to_brutus(res_->ulFuzzyLevel, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SContentRestriction_i::ulPropTag(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag, retval);

	return retval;
}

::BRUTUS::SPropValue * BRUTUS_SContentRestriction_i::lpProp(void)

{
	::BRUTUS::SPropValue_var retval;
	try {
		retval = new ::BRUTUS::SPropValue;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		throw ::CORBA::NO_MEMORY();
	}
	spropvalue_mapi_to_brutus(res_->lpProp, retval, mapi_session_, false, poa_.in());

	return retval._retn();
}

BRUTUS_SPropertyRestriction_i::BRUTUS_SPropertyRestriction_i(::SPropertyRestriction *Res,
							     LPMAPISESSION MAPISession,
							     ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::RELOP_TYPE BRUTUS_SPropertyRestriction_i::relop(void)

{
	::BRUTUS::RELOP_TYPE retval = 0;
	relop_mapi_to_brutus(res_->relop, retval);

	return retval;
}


::CORBA::ULong BRUTUS_SPropertyRestriction_i::ulPropTag(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag, retval);

	return retval;
}


::BRUTUS::SPropValue * BRUTUS_SPropertyRestriction_i::lpProp(void)

{
	::BRUTUS::SPropValue_var retval;
	try {
		retval = new ::BRUTUS::SPropValue;
	}
	catch (std::bad_alloc &) {
		BRUTUS_LOG_ERR("No memory");
		throw ::CORBA::NO_MEMORY();
	}
	spropvalue_mapi_to_brutus(res_->lpProp, retval, mapi_session_, false, poa_.in());

	return retval._retn();
}


BRUTUS_SComparePropsRestriction_i::BRUTUS_SComparePropsRestriction_i(::SComparePropsRestriction *Res,
								     LPMAPISESSION MAPISession,
								     ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
}

::BRUTUS::RELOP_TYPE BRUTUS_SComparePropsRestriction_i::relop(void)

{
	::BRUTUS::RELOP_TYPE retval = 0;
	relop_mapi_to_brutus(res_->relop, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SComparePropsRestriction_i::ulPropTag1(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag1, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SComparePropsRestriction_i::ulPropTag2(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag2, retval);

	return retval;
}

BRUTUS_SBitMaskRestriction_i::BRUTUS_SBitMaskRestriction_i(::SBitMaskRestriction *Res,
							   LPMAPISESSION MAPISession,
							   ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
}

::BRUTUS::BMR_TYPE BRUTUS_SBitMaskRestriction_i::relBMR(void)

{
	::BRUTUS::BMR_TYPE retval = 0;
	bmr_mapi_to_brutus(res_->relBMR, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SBitMaskRestriction_i::ulPropTag(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SBitMaskRestriction_i::ulMask(void)

{
	return (::CORBA::ULong)res_->ulMask;
}

BRUTUS_SSizeRestriction_i::BRUTUS_SSizeRestriction_i(::SSizeRestriction *Res,
						     LPMAPISESSION MAPISession,
						     ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
}

::BRUTUS::RELOP_TYPE BRUTUS_SSizeRestriction_i::relop(void)

{
	::BRUTUS::RELOP_TYPE retval = 0;
	relop_mapi_to_brutus(res_->relop, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SSizeRestriction_i::ulPropTag(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SSizeRestriction_i::cb(void)

{
	return (::CORBA::ULong)res_->cb;
}

BRUTUS_SExistRestriction_i::BRUTUS_SExistRestriction_i(::SExistRestriction *Res,
						       LPMAPISESSION MAPISession,
						       ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
}

::CORBA::ULong BRUTUS_SExistRestriction_i::ulReserved1(void)

{
	return (::CORBA::ULong)res_->ulReserved1;
}

void BRUTUS_SExistRestriction_i::ulReserved1(::CORBA::ULong ulReserved1)

{
	res_->ulReserved1 = (unsigned long)ulReserved1;
}

::CORBA::ULong BRUTUS_SExistRestriction_i::ulPropTag(void)

{
	::CORBA::ULong retval = 0;
	proptag_mapi_to_brutus(res_->ulPropTag, retval);

	return retval;
}

::CORBA::ULong BRUTUS_SExistRestriction_i::ulReserved2(void)

{
	return (::CORBA::ULong)res_->ulReserved2;
}

void BRUTUS_SExistRestriction_i::ulReserved2(::CORBA::ULong ulReserved2)

{
	res_->ulReserved2 = (unsigned long)ulReserved2;
}


BRUTUS_SSubRestriction_i::BRUTUS_SSubRestriction_i(::SSubRestriction *Res,
						   LPMAPISESSION MAPISession,
						   ::PortableServer::POA_ptr Poa)
	: res_(Res), mapi_session_(MAPISession),poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::BDEFINE BRUTUS_SSubRestriction_i::ulSubObject(void)

{
	::BRUTUS::BDEFINE retval = 0;
	sub_object_mapi_to_brutus(res_->ulSubObject, retval);

	return retval;
}

::BRUTUS::SRestriction * BRUTUS_SSubRestriction_i::lpRes(void)

{
	::BRUTUS::SRestriction_var retval;
	srestriction_mapi_to_brutus(res_->lpRes, mapi_session_, retval.out(), poa_.in());

	return retval._retn();
}


BRUTUS_SCommentRestriction_i::BRUTUS_SCommentRestriction_i(::SCommentRestriction *Res,
							   LPMAPISESSION MAPISession,
							   ::PortableServer::POA_ptr Poa)
	: res_(Res),
	  mapi_session_(MAPISession),
	  poa_(::PortableServer::POA::_duplicate(Poa))
{
	mapi_session_->AddRef();
}

::BRUTUS::SRestriction * BRUTUS_SCommentRestriction_i::lpRes(void)

{
	::BRUTUS::SRestriction_var retval;
	srestriction_mapi_to_brutus(res_->lpRes, mapi_session_, retval.out(), poa_.in());

	return retval._retn();
}


::BRUTUS::seq_SPropValue * BRUTUS_SCommentRestriction_i::lpProp(void)

{
	::BRUTUS::seq_SPropValue_var retval;
	spropvalue_array_mapi_to_brutus(res_->cValues, res_->lpProp, retval.inout(), mapi_session_, false, poa_.in());

	return retval._retn();
}
