/* -*- 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 "ieihc_utils.h"
#include "conv_utils.h"
#include "obj_utils.h"
#include "templates.i"
#include "utils/macros.h"

#include "edkcode.h"

inline BRUTUS::BDEFINE brutus_flags(const ULONG Flags)
{
	ULONG flags = Flags;
	BRUTUS::BDEFINE retval = 0;

	if (flags & SYNC_UNICODE) {
		retval |= BRUTUS::BRUTUS_SYNC_UNICODE;
		FLAGS_OFF(DWORD, flags, SYNC_UNICODE);
	}
	if (flags & SYNC_ASSOCIATED) {
		retval |= BRUTUS::BRUTUS_SYNC_ASSOCIATED;
		FLAGS_OFF(DWORD, flags, SYNC_ASSOCIATED);
	}
	if (flags & SYNC_NO_DELETIONS) {
		retval |= BRUTUS::BRUTUS_SYNC_NO_DELETIONS;
		FLAGS_OFF(DWORD, flags, SYNC_NO_DELETIONS);
	}
	if (flags & SYNC_READ_STATE) {
		retval |= BRUTUS::BRUTUS_SYNC_READ_STATE;
		FLAGS_OFF(DWORD, flags, SYNC_READ_STATE);
	}
	if (flags & SYNC_NORMAL) {
		retval |= BRUTUS::BRUTUS_SYNC_NORMAL;
		FLAGS_OFF(DWORD, flags, SYNC_NORMAL);
	}

	if (flags) {
		char msg[128] = {0};
		sprintf_s(msg, sizeof(msg), "Unknown flag(s) from MAPI : %X", flags);
		BRUTUS_LOG_BUG(msg);
	}

	return retval;
}

STDMETHODIMP CExchangeImportHierarchyChanges::GetLastError(HRESULT hResult,
							   ULONG ulFlags,
							   LPMAPIERROR FAR * lppMAPIError)
{
	BRUTUS::BRESULT br;
	HRESULT hr;

	if (!hresult_to_bresult(hResult, br)) {
		BRUTUS_LOG_BUG("Could not convert HRESULT into BRESULT");
		hr = E_FAIL;
	}
	CORBA::ULong flags = ulFlags;
	BRUTUS::MAPIERROR_var b_error;

	try {
		br = brutus_obj_->GetLastError(br,
					       flags,
					       b_error.out());
	}
	catch (...) {
		BRUTUS_LOG_BUG("Exception caught from client in CExchangeImportHierarchyChanges::GetLastError()");
		return E_FAIL;
	}

	if (!bresult_to_hresult(br, hr)) {
		BRUTUS_LOG_BUG("Could not convert BRESULT into HRESULT");
		hr = E_FAIL;
	}
	if(!mapierror_brutus_to_mapi(b_error,
				     NULL,
				     *lppMAPIError)) {
		BRUTUS_LOG_BUG("Could not convert BRUTUS::MAPIERROR into MAPIERROR");
		hr = E_FAIL;
	}

	return hr;
}

STDMETHODIMP CExchangeImportHierarchyChanges::Config(LPSTREAM lpStream,
						     ULONG ulFlags)
{
	BRUTUS::IStream_var brutus_stream = BRUTUS::IStream::_nil();

	stream_ = lpStream;
	if (stream_) {
		stream_->AddRef();
		brutus_stream = create_object<BRUTUS_IStream_i, BRUTUS::IStream, LPSTREAM>
			(stream_, poa_.in(), mapi_session_);
	}

	CORBA::ULong flags = brutus_flags(ulFlags);

	BRUTUS::BRESULT br;
	try {
		br = brutus_obj_->Config(brutus_stream.in(),
					 flags);
	}
	catch (...) {
		BRUTUS_LOG_BUG("Exception caught from client in CExchangeImportHierarchyChanges::Config()");
		return E_FAIL;
	}
	HRESULT hr;
	if (!bresult_to_hresult(br, hr)) {
		BRUTUS_LOG_BUG("Could not convert BRESULT into HRESULT");
		hr = E_FAIL;
	}

	return hr;
}

STDMETHODIMP CExchangeImportHierarchyChanges::UpdateState(LPSTREAM lpStream)
{
	BRUTUS::IStream_var brutus_stream = BRUTUS::IStream::_nil();
	if (lpStream) {
		lpStream->AddRef();
		brutus_stream = create_object<BRUTUS_IStream_i, BRUTUS::IStream, LPSTREAM>
			(lpStream, poa_.in(), mapi_session_);
	}

	BRUTUS::BRESULT br;
	try {
		br = brutus_obj_->UpdateState(brutus_stream.in());
	}
	catch (...) {
		BRUTUS_LOG_BUG("Exception caught from client in CExchangeImportHierarchyChanges::UpdateState()");
		return E_FAIL;
	}
	HRESULT hr;
	if (!bresult_to_hresult(br, hr)) {
		BRUTUS_LOG_BUG("Could not convert BRESULT into HRESULT");
		hr = E_FAIL;
	}

	return hr;
}

STDMETHODIMP CExchangeImportHierarchyChanges::ImportFolderChange(ULONG cValue,
								 LPSPropValue lpPropArray)
{
	BRUTUS::seq_SPropValue brutus_propvalue_array;
	if (!spropvalue_array_mapi_to_brutus(cValue, lpPropArray, brutus_propvalue_array, mapi_session_, false, poa_.in()))
		return EC_EDK_E_OUTOFMEMORY;

	BRUTUS::BRESULT br;
	try {
		br = brutus_obj_->ImportFolderChange(brutus_propvalue_array);
	}
	catch (...) {
		BRUTUS_LOG_BUG("Exception caught from client in CExchangeImportHierarchyChanges::ImportFolderChange()");
		return E_FAIL;
	}
	HRESULT hr;
	if (!bresult_to_hresult(br, hr)) {
		BRUTUS_LOG_BUG("Could not convert BRESULT into HRESULT");
		hr = E_FAIL;
	}

	return hr;
}

STDMETHODIMP CExchangeImportHierarchyChanges::ImportFolderDeletion(ULONG ulFlags,
								   LPENTRYLIST lpSourceEntryList)
{
	if (!lpSourceEntryList)
		return EC_EDK_E_INVALIDARG;

	BRUTUS::BDEFINE flags = brutus_flags(ulFlags);
	BRUTUS::SBinaryArray brutus_bin_array;

	if (!sbinary_array_mapi_to_brutus(lpSourceEntryList, brutus_bin_array))
		return EC_EDK_E_OUTOFMEMORY;

	BRUTUS::BRESULT br;
	try {
		br = brutus_obj_->ImportFolderDeletion(flags,
						       brutus_bin_array);
	}
	catch (...) {
		BRUTUS_LOG_BUG("Exception caught from client in CExchangeImportHierarchyChanges::ImportFolderDeletion()");
		return E_FAIL;
	}
	HRESULT hr;
	if (!bresult_to_hresult(br, hr)) {
		BRUTUS_LOG_BUG("Could not convert BRESULT into HRESULT");
		hr = E_FAIL;
	}

	return hr;
}
