/*
 * 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 <base/util/ArrayList.h>
#include <vector>

#include "Event.h"
#include "IServerExchangeManager.h"
#include "PortableThread.h"

#include "executionqueue/ICommand.h"
#include "serverexchange/commands/AlertCodes.h"
#include "serverexchange/wrappers/SCommandAdapter.h"
#include "serverexchange/IConnection.h"
#include "serverexchange/ServerPoller.h"


namespace NS_DM_Client
{
	namespace NS_Common {
		class Starter;
	}

	namespace NS_Communication
	{
		class ConnectionInfo;
		class FirmwareManager;
		class SyncCall;
		class WIBConnector;

		/// TODO - update desc.
		/// Class implements ...
		class ServerExchangeManager : public IServerExchangeManager, private Thread
		{
		public:
			ServerExchangeManager();
			virtual ~ServerExchangeManager();

			virtual bool Init(const StringMap& settings, const String& loggerInstance, ProfileComponentsHolder& pch);
			virtual bool Start();
			virtual bool Stop();
			virtual void Release();
					void Wait();

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

			virtual IConnection * DefaultConnection();

			virtual void HandleNetworkEntrance(int homeNspID, const char* operatorName, bool startWIB);
			virtual void NotifyDiagnosticsReady(String &serverID, String &origID);
			virtual bool HasAccountFor(String &serverID);
			virtual void SetConnectionsInfo(ConnInfoList &);

			virtual void ProcessBootstrapMessage(const char *bsm, uint length);
			virtual void RequestFWUpdate(bool userInitiated, const char *fumouri, int data);
			virtual void RequestSessionStart(const NS_NotificationListener::SessionInfo& sessionInfo);
			        void Restart();
			virtual void StartClientSession();

			virtual FirmwareManager* GetFirmwareManager();

			virtual void SetDevInfo(Funambol::DevInf &devInf);
			virtual void SetServerPollerInfo(bool pollingSupported, int pollingInterval, int pollingAttempts);

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

			virtual void StartWIB(HomeNSPID nspID, const char* operatorName = NULL);

		private:
			typedef std::map<String, IConnection *> Connections;

			volatile bool m_haveBMProcessed;
			bool m_startOnLAN;
			bool m_startedOnLAN;
			volatile bool m_threadStarted;
			bool m_useShortTimeout;

			bool m_wibCipherHeaderPresent;
			bool m_wibPlainBootstrap;
			int  m_wibRetriesCount;
			int  m_wibRetryInterval;

			uint m_connectionDelay;

			struct tagPollingInfo{
				bool   pollingSupported;
				int    pollingInterval;
				int    pollingAttempts;
				tagPollingInfo() {
					pollingSupported = false;
					pollingInterval = pollingAttempts = 0;
				}
			} m_pollingInfo;

			ConnectionSettings   m_settings;
			IConnection        * m_pDefaultConnection;
			FirmwareManager    * m_pFirmwareManager;
			ProfileComponentsHolder *m_pProfileHolder;
			SyncCall           * m_pSyncCall;
			WIBConnector       * m_pWIBConnector;
			NS_Common::Starter * m_pWIBThread;

			DevInfPtr            m_ptrDevInfo;
			ConnInfoList         m_connInfoList;
			Connections          m_connections;
			ServerPoller         m_serverPoller;
			String               m_defaultFWURI;
			String               m_defaultAccountName;
			String               m_drmdAccountName;
			String               m_OEMSharedKey;
			String               m_wibDnsServer;
			String               m_wibServiceDiscoveryTarget;

			// this mutex is locked when command/list of commands is added
			NS_Common::CritSection  m_csAddCommand;

			// this mutex is locked when SEM start running
			NS_Common::CritSection  m_csWaitComplete;

			void configureDRMDAccount(ConnectionInfo &ci);
			bool isDRMDServer(String &serverID);
			void startServerPoller();
			IConnection * startConnection(String &);
			void stopConnections();
		};
	}
}

