/* -*- 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/>.
 */

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef __IMAPITABLES_IMPL_H_
#define __IMAPITABLES_IMPL_H_

#include "IMAPITableS.h"
#include "utils/macros.h"
#include "advise_utils.h"

#define MAPIGUID_H // do not include mapiguid.h
#include <mapix.h>

#include "Brutus_Loader_Impl_Export.h"

class Brutus_Loader_Impl_Export BRUTUS_IMAPITable_i : public virtual POA_BRUTUS::IMAPITable,
						      public virtual ::PortableServer::RefCountServantBase
{
public:
	BRUTUS_IMAPITable_i(LPMAPITABLE MAPITable,
			    LPMAPISESSION MAPISession,
			    ::PortableServer::POA_ptr Poa);


	virtual ::BRUTUS::BRESULT GetLastError(::BRUTUS::BRESULT ReturnCode,
					       ::BRUTUS::BDEFINE ulFlags,
					       ::BRUTUS::MAPIERROR_out lppMAPIError);

	virtual ::BRUTUS::BRESULT Advise(::BRUTUS::BDEFINE ulEventMask,
					 ::BRUTUS::IMAPIAdviseSink_ptr lpAdviseSink,
					 ::CORBA::ULong_out lpulConnection);

	virtual ::BRUTUS::BRESULT Unadvise(::CORBA::ULong ulConnection);

	virtual ::BRUTUS::BRESULT GetStatus(::CORBA::ULong_out lpulTableStatus,
					    ::CORBA::ULong_out lpulTableType);

	virtual ::BRUTUS::BRESULT SetColumns(const ::BRUTUS::SPropTagArray & lpPropTagArray,
					     ::BRUTUS::BDEFINE ulFlags);

	virtual ::BRUTUS::BRESULT QueryColumns(::BRUTUS::BDEFINE ulFlags,
					       ::BRUTUS::SPropTagArray_out lpPropTagArray);

	virtual ::BRUTUS::BRESULT GetRowCount(::BRUTUS::BDEFINE ulFlags,
					      ::CORBA::ULong_out lpulCount);

	virtual ::BRUTUS::BRESULT SeekRow(::CORBA::ULong bkOrigin,
					  ::CORBA::Long lRowCount,
					  ::CORBA::Long_out lplRowsSought);

	virtual ::BRUTUS::BRESULT SeekRowApprox(::CORBA::ULong ulNumerator,
						::CORBA::ULong ulDenominator);

	virtual ::BRUTUS::BRESULT QueryPosition(::CORBA::ULong_out lpulRow,
						::CORBA::ULong_out lpulNumerator,
						::CORBA::ULong_out lpulDenominator);

	virtual ::BRUTUS::BRESULT FindRow(::BRUTUS::SRestrictionContainer_ptr lpRestriction,
					  ::CORBA::ULong bkOrigin,
					  ::BRUTUS::BDEFINE ulFlags);

	virtual ::BRUTUS::BRESULT Restrict(::BRUTUS::SRestrictionContainer_ptr lpRestriction,
					   ::BRUTUS::BDEFINE ulFlags);

	virtual ::BRUTUS::BRESULT CreateBookmark(::CORBA::ULong_out lpbkPosition);

	virtual ::BRUTUS::BRESULT FreeBookmark(::CORBA::ULong bkPosition);

	virtual ::BRUTUS::BRESULT SortTable(const ::BRUTUS::SSortOrderSet & lpSortCriteria,
					    ::BRUTUS::BDEFINE ulFlags);

	virtual ::BRUTUS::BRESULT QuerySortOrder(::BRUTUS::SSortOrderSet_out lppSortCriteria);

	virtual ::BRUTUS::BRESULT QueryRows(::CORBA::Long lRowCount,
					    ::BRUTUS::BDEFINE ulFlags,
					    ::BRUTUS::SRowSet_out lppRows);

	virtual ::BRUTUS::BRESULT Abort(void);

	virtual ::BRUTUS::BRESULT ExpandRow(const ::BRUTUS::seq_octet & pbInstanceKey,
					    ::CORBA::ULong ulRowCount,
					    ::BRUTUS::BDEFINE ulFlags,
					    ::BRUTUS::SRowSet_out lppRows,
					    ::CORBA::ULong_out lpulMoreRows);

	virtual ::BRUTUS::BRESULT CollapseRow(const ::BRUTUS::seq_octet & pbInstanceKey,
					      ::BRUTUS::BDEFINE ulFlags,
					      ::CORBA::ULong_out lpulRowCount);

	virtual ::BRUTUS::BRESULT WaitForCompletion(::BRUTUS::BDEFINE ulFlags,
						    ::CORBA::ULong ulTimeout,
						    ::CORBA::ULong & lpulTableStatus);

	virtual ::BRUTUS::BRESULT GetCollapseState(::BRUTUS::BDEFINE ulFlags,
						   const ::BRUTUS::seq_octet & lpbInstanceKey,
						   ::BRUTUS::seq_octet_out lppbCollapseState);

	virtual ::BRUTUS::BRESULT SetCollapseState(::BRUTUS::BDEFINE ulFlags,
						   const ::BRUTUS::seq_octet & pbCollapseState,
						   ::CORBA::ULong_out lpbkLocation);

	virtual ::BRUTUS::BRESULT GetLocalPointer(::CORBA::ULongLong_out Pointer);

	virtual ::BRUTUS::BRESULT QueryInterface(const char *iid,
						 ::BRUTUS::IUnknown_out ppvObject);

	virtual void Destroy(::CORBA::ULong InstanceID);

private:
	// Skeleton constructor
	BRUTUS_IMAPITable_i (void)
	{ };

	// Destructor
	virtual ~BRUTUS_IMAPITable_i(void)
	{
		BRUTUS_LOG_INF("BRUTUS_IMAPITable_i destructor being run");
		try {
			for (unsigned long n = 0; n < advise_sinks_.length(); n++)
				mapi_table_->Unadvise(advise_sinks_[n]);
			advise_sinks_.Clear();

			BRUTUS_LOG_INF("~BRUTUS_IMAPITable_i - Releasing mapi_table_");
			mapi_table_->Release();

			BRUTUS_LOG_INF("~BRUTUS_IMAPITable_i - Releasing mapi_session_");
			mapi_session_->Release();
		}
		catch (...) {
			BRUTUS_LOG_ERR("Exception caught");
		}
		BRUTUS_LOG_INF("BRUTUS_IMAPITable_i destructor is done");
	};

	LPMAPITABLE mapi_table_;
	LPMAPISESSION mapi_session_;
	::PortableServer::POA_var poa_;

	Sinks advise_sinks_;
	ACE_RW_Mutex mutex_;
};


#endif /* __IMAPITABLES_IMPL_H_  */
