/* -*- 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 _IEICC_UTILS_H_
#define _IEICC_UTILS_H_

#include "IExchangeImportContentsChangesC.h"
#include "edkguid.h"
#include "guid.h"

#include <tao/PortableServer/PortableServer.h>

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

class CExchangeImportContentsChanges : public virtual IExchangeImportContentsChanges {
public:
	CExchangeImportContentsChanges(BRUTUS::IExchangeImportContentsChanges_ptr BrutusIEIHC,
				       LPMAPISESSION MAPISession,
				       PortableServer::POA_ptr Poa)
		:
		ref_count_(0),
		stream_(NULL),
		mapi_session_(MAPISession),
		poa_(PortableServer::POA::_duplicate(Poa)),
		brutus_obj_(BRUTUS::IExchangeImportContentsChanges::_duplicate(BrutusIEIHC))
		{
			mapi_session_->AddRef();
			InitializeCriticalSection(&critical_section_);
			AddRef();
		};

	STDMETHODIMP QueryInterface(REFIID riid,
				    LPVOID *ppvObj)
		{
			HRESULT hr = E_NOINTERFACE;
			*ppvObj = 0;

			if ((IID_IUnknown == riid) || (IID_IExchangeImportContentsChanges == riid)) {
				*ppvObj = (IExchangeImportContentsChanges*)this;
				AddRef();
				hr = S_OK;
			}

			return hr;
		};

	STDMETHODIMP_(ULONG) AddRef()
		{
			EnterCriticalSection(&critical_section_);
			ULONG count = ++ref_count_;
			LeaveCriticalSection(&critical_section_);

			return count;
		};

	STDMETHODIMP_(ULONG) Release()
		{
			EnterCriticalSection(&critical_section_);
			ULONG count = --ref_count_;
			LeaveCriticalSection(&critical_section_);
			if (!count)
				delete this;

			return count;
		};

	virtual HRESULT STDMETHODCALLTYPE GetLastError(HRESULT hResult,
						       ULONG ulFlags,
						       LPMAPIERROR FAR * lppMAPIError);

	virtual HRESULT STDMETHODCALLTYPE Config(LPSTREAM lpStream,
						 ULONG ulFlags);

	virtual HRESULT STDMETHODCALLTYPE UpdateState(LPSTREAM lpStream);

	virtual HRESULT STDMETHODCALLTYPE ImportMessageChange(ULONG cValue,
							      LPSPropValue lpPropArray,
							      ULONG ulFlags,
							      LPMESSAGE * lppMessage);

	virtual HRESULT STDMETHODCALLTYPE ImportMessageDeletion(ULONG ulFlags,
								LPENTRYLIST lpSourceEntryList);

	virtual HRESULT STDMETHODCALLTYPE ImportPerUserReadStateChange(ULONG cElements,
								       LPREADSTATE lpReadState);

	virtual HRESULT STDMETHODCALLTYPE ImportMessageMove(ULONG cbSourceKeySrcFolder,
							    BYTE FAR * pbSourceKeySrcFolder,
							    ULONG cbSourceKeySrcMessage,
							    BYTE FAR * pbSourceKeySrcMessage,
							    ULONG cbPCLMessage,
							    BYTE FAR * pbPCLMessage,
							    ULONG cbSourceKeyDestMessage,
							    BYTE FAR * pbSourceKeyDestMessage,
							    ULONG cbChangeNumDestMessage,
							    BYTE FAR * pbChangeNumDestMessage);

private:
	~CExchangeImportContentsChanges()
		{
			if (stream_)
				stream_->Release();

			if (mapi_session_)
				mapi_session_->Release();

			DeleteCriticalSection(&critical_section_);
			brutus_obj_->Destroy(0);
		};

	LONG ref_count_;
	LPSTREAM stream_;
	LPMAPISESSION mapi_session_;
	PortableServer::POA_var poa_;
	CRITICAL_SECTION critical_section_;
	BRUTUS::IExchangeImportContentsChanges_var brutus_obj_;
};

#endif //  _IEICC_UTILS_H_
