/*
 * Copyright 2009 Funambol, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $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 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 notifyAuthenticationFailure();
			virtual void notifySessionAbort();
			virtual void notifySessionStart();
			virtual void notifySessionFinished();

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

			// this mutex is locked when one wants to work with
			NS_Common::Event        m_evHasCommands;
			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::SAlertCommandPtr m_initialAlert;
			NS_SyncMLCommand::AlertCode        m_initialAlertCode;
			NS_SyncMLCommand::CommandStorage   m_waitingcommands;
			
			std::vector<NS_SyncMLCommand::SAlertCommandPtr> m_alerts;

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

