/*
 * Copyright (C) 2009 - 2010 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
 *
 * 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 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 or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */
/* $Id$ */

#pragma once

#include "Event.h"
#include "PortableThread.h"
#include "executionqueue/ICommand.h"
#include "serverexchange/ICommandsSink.h"
#include "serverexchange/IConnection.h"
#include "serverexchange/commands/AlertCodes.h"
#include "serverexchange/wrappers/SCommandAdapter.h"
#include "serverexchange/CommandStorage.h"
#include "serverexchange/session/ISession.h"
#include "NotificationListener/SessionInfo.h"


namespace NS_DM_Client
{
	namespace NS_SyncMLCommand {
		class ICommandsSink;
	}

	namespace NS_Communication
	{
		class ConnectionInfo;

		/// TODO - update desc.
		/// Class implements interaction with the DM server.
		/// Starting session(authentication), receiving and handling of the DM commands, sending responses,
		/// processing bootstrap message and other feature are incorporated into the implementation.
		/// To process bootstrap message or message from the DM server the ResponseProcessor class is used.
		class Connection : public IConnection, private Thread
		{
		public:
			Connection(ConnectionInfo &);
			virtual ~Connection();

			virtual void Abort();

			virtual void AddCommand(NS_SyncMLCommand::SCommandPtr ptrCommand, const char *serverid = NULL);
			virtual void AddCommands(NS_SyncMLCommand::SCommandsArray &commands, const char *serverid = NULL);

			virtual void NotifySessionStarted();

			virtual void RequestSessionStart(const NS_NotificationListener::SessionInfo& sessionInfo);
			virtual void RequestFWUpdate(bool userInitiated, const char *fumouri, int data);

			virtual void SetPCH(ProfileComponentsHolder &);
			virtual void Start(NS_Common::Event *e = NULL);
			virtual void StartSession(const NS_SyncMLCommand::AlertCode ac = NS_SyncMLCommand::AC_CLIENT_INITIATED_MGMT);
			virtual void StartSession(NS_SyncMLCommand::SAlertCommandPtr);
			virtual void Stop();

			virtual void Wait();

			virtual ConnectionInfo & Info()       { return m_connectionInfo; };
			virtual bool IsRunning()              { return m_threadStarted; };

			friend class ResponseProcessor;
			virtual void run();  // Funambol::FThread

		protected:
			ConnectionInfo & m_connectionInfo;
			ProfileComponentsHolder *m_pProfileHolder;

			virtual void finishSession();
			virtual void notifySessionAborted();
			virtual void notifySessionStarted();
			virtual void notifySessionFinished();

		private:
			bool          m_addInitialAlert;
			bool          m_startNotified;
			volatile bool m_threadStarted;

			// this mutex is locked when one wants to work with
			NS_Common::CondVariable m_condHasCommands;
			NS_Common::CritSection  m_csConnection;
			NS_Common::CritSection  m_csHasCommands;
			NS_Common::CritSection  m_csWaitComplete;

			NS_Common::Event * m_pEventStarted;
			ISession         * m_pSession;

			NS_SyncMLCommand::AlertCode m_initialAlertCode;
			NS_SyncMLCommand::CommandStorage m_waitingcommands;

			void createSession();
			void initiateConnection(const NS_SyncMLCommand::AlertCode alertCode, const NS_NotificationListener::SessionInfo* sessionInfo = 0);
			bool isAccessConfigValid();
		};
	}
}

