/* -*- 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 "idl/IMAPISessionC.h"
#include "idl/BrutusCheckC.h"
#include <string>
#include <map>

class ProxySession {
public:
	ProxySession(::BRUTUS::IMAPISession_ptr mapi_session,
		     const char * const windows_user,
		     const char * const windows_domain,
		     HANDLE process_handle);

	~ProxySession(void);

	void
	Terminate(void);

	::BRUTUS::IMAPISession_var mapi_session_;
	char *windows_user_;
	char *windows_domain_;
	HANDLE process_handle_;
};


class ProxyCache {
public:
	ProxyCache(void)
		{ 
		};

	~ProxyCache(void)
		{
			for (cache_iterator i = proxy_list_.begin(); i != proxy_list_.end(); i++)
				delete i->second;
			proxy_list_.clear();
		};

	::CORBA::ULong
	lookup(const char * const mapi_profile,
	       const char * const windows_user,
	       const char * const windows_domain, // NULL if UPN authentication is used
	       ::BRUTUS::BrutusCheck_ptr lifeline,
	       ::BRUTUS::IMAPISession_out mapi_session);

	void
	insert(const char * const mapi_profile,
	       const char * const windows_user,
	       const char * const windows_domain, // NULL if UPN authentication is used
	       HANDLE process_handle,
	       ::BRUTUS::IMAPISession_ptr mapi_session);

	void
	remove(const char * const mapi_profile,
	       bool terminate_proxy = false);

private:
	std::map<std::string, ProxySession*> proxy_list_;
	typedef std::map<std::string, ProxySession*>::iterator cache_iterator;
	ACE_RW_Mutex mutex_;
};

class F2T_Process {
public:
	F2T_Process(void)
		: spawned_(false),
		  cmd_line_(NULL)
		{
			process_info_.hProcess = NULL;
			process_info_.hThread = NULL;
		};

	~F2T_Process(void)
		{
			if (cmd_line_)
				free(cmd_line_);

			try {
				if (process_info_.hProcess)
					CloseHandle(process_info_.hProcess);
			}
			catch (...) {
				ACE_DEBUG((LM_CRITICAL, ACE_TEXT("%N:%l - Unknown C++ exception\n")));
			}
		};

	HANDLE handle_retn(void);

	void kill(void);

	pid_t getpid(void);

	HANDLE
	F2T_Process::gethandle(void);

	bool is_running (void);

	void prepare(char **CommandLine);

	pid_t spawn(const char * const user,
		    const char * const domain,
		    const char * const password);
private:
	pid_t spawn_process(const char * const user,
			    const char * const domain,
			    const char * const password,
			    LPTSTR command,
			    PROCESS_INFORMATION *pi);
private:
	bool spawned_;
	LPTSTR cmd_line_;
	PROCESS_INFORMATION process_info_;
};

class ProxyProcess : public F2T_Process {
public:
	ProxyProcess(const char * const LifeLineIOR,
		     const char * const MAPIProfileName,
		     const char * const WindowsUserName,
		     const char * const WindowsDomainName,
		     const char * const WindowsUserPassword,
		     const char * const MAPIProfilePassword,
		     const char * const MailboxName,
		     const char * const ServerName,
		     const char * const server_type,
		     const char * const logon_flags,
		     const char * const profile_flags);

	~ProxyProcess(void)
		{
		};
};

