using System;
using System.Collections.Generic;
using System.Text;

using EA.GameTalkMessages;

namespace EA.GameTalk
{
	/// <summary>
	/// Interface that was going to be used to come to an agreement on a common API that all our comm layer technologies could share
	/// </summary>
	public interface IGameTalkInstance
	{
		/// <summary>
		/// Does our instance have a connection with the server
		/// </summary>
		bool IsConnected
		{
			get;
		}

		#region Initialize Methods
		/// <summary>
		/// This probably wants to be made private (thus not exposed through this interface) - since this should be getting called directly from the constructor
		/// </summary>
		void Initialize();
		
		/// <summary>
		/// Initialize the communication
		/// </summary>
		/// <param name="targetName">The name of the client to connect</param>
		void Initialize(string targetName);

		/// <summary>
		/// Initialize the communication
		/// </summary>
		/// <param name="targetName">The name of the client to connect</param>
		/// <param name="serverName">The server name to connect</param>
		void Initialize(string targetName, string serverName);

		/// <summary>
		/// Initialize the communication
		/// </summary>
		/// <param name="targetName">The name of the client to connect</param>
		/// <param name="serverName">The server name to connect</param>
		/// <param name="portNum">The port that the server is listening on (to which we will connect)</param>
		void Initialize(string targetName, string serverName, int portNum);

		/// <summary>
		/// Initialize the communication
		/// </summary>
		/// <param name="targetName"></param>
		/// <param name="serverName"></param>
		/// <param name="platform"></param>
		void Initialize(string targetName, string serverName, string platform);

		/// <summary>
		/// Initialize the communication
		/// </summary>
		/// <param name="targetName"></param>
		/// <param name="serverName"></param>
		/// <param name="platform"></param>
		/// <param name="isService">This lets GameTalk know if the process starting GameTalk is
		/// a service.  If it is a service starting GameTalk - then it will not try to install
		/// or start the GameTalkMonitor - since Services shouldn't start stand-alone applications</param>
		void Initialize(string targetName, string serverName, string platform, bool isService);

		/// <summary>
		/// Initialize the communication
		/// </summary>
		/// <param name="targetName"></param>
		/// <param name="serverName"></param>
		/// <param name="platform"></param>
		/// <param name="isService">This lets GameTalk know if the process starting GameTalk is
		/// a service.  If it is a service starting GameTalk - then it will not try to install
		/// or start the GameTalkMonitor - since Services shouldn't start stand-alone applications</param>
		/// <param name="portNum">The port that the server is listening on (to which we will connect)</param>
		void Initialize(string targetName, string serverName, string platform, bool isService, int portNum);
		#endregion

		#region Send Methods
		/// <summary>
		/// Register a message handler for a specific channel
		/// 
		/// We probably want to change the name-space/scope of MessageReceivedDelegate
		/// to be in a class in IGameTalkInstance - but this will break existing users' code
		/// </summary>
		/// <param name="callback">The callback handler</param>
		/// <param name="channel">The channel for filtering</param>
		bool RegisterMessageHandler(GameTalkInstance.MessageReceivedDelegate callback, string channel);

		/// <summary>
		/// Unregister a message handler for a specific channel
		/// 
		/// We probably want to change the name-space/scope of MessageReceivedDelegate
		/// to be in a class in IGameTalkInstance - but this will break existing users' code
		/// </summary>
		/// <param name="callback">The callback handler</param>
		bool UnregisterMessageHandler(GameTalkInstance.MessageReceivedDelegate callback);
		
		/// <summary>
		/// User can use this to send their Message over the network to the specified target
		/// </summary>
		/// <param name="target"></param>
		/// <param name="message"></param>
		/// <returns></returns>
		bool Send(string target, GameTalkMessage message);

		#endregion


		#region Shutdown Methods

		/// <summary>
		/// Lets the server know the user is shutting down their connection
		/// </summary>
		/// <returns></returns>
		Connection.ConnectionResult SendShutDownMessage();

		/// <summary>
		/// Release the client.
		/// </summary>
		bool Shutdown();

		#endregion

		#region Configuration Send Methods
		/// <summary>
		/// Tell the server to start buffering messages from the current client to the requested target
		/// </summary>
		/// <param name="target"></param>
		/// <param name="maxBufferedMessages">The maximum number of messages that will be buffered for this particular client</param>
		/// <param name="reset">Whether to clear the buffer</param>
		/// <returns></returns>
		bool StartBuffering(string target, int maxBufferedMessages, bool reset);

		/// <summary>
		/// Tells the server to stop buffering any messages from the current client for the specified target
		/// </summary>
		/// <param name="target"></param>
		/// <param name="reset">Whether to clear the buffer</param>
		/// <returns></returns>
		bool StopBuffering(string target, bool reset);

		/// <summary>
		/// This is a request to have the server send its version to the client
		/// This response will be received asynchronously (in the user's registered call-back)
		/// </summary>
		/// <returns></returns>
		bool RequestServerVersion();

		/// <summary>
		/// This is a request to have the server send its registered targets to the client
		/// This response will be received asynchronously (in the user's registered call-back)
		/// </summary>
		/// <returns></returns>
		bool RequestRegisteredTargets();

		/// <summary>
		/// Using this allows us to poll the GameTalkServer and thus get a valid return value from
		/// the IsConnected property
		/// </summary>
		/// <returns></returns>
		bool SendIsAlivePing();

		/// <summary>
		/// This requests the list of all currently connected clients
		/// The response is received on the GameTalkMessage.sServerMessageID channel
		/// </summary>
		/// <returns></returns>
		bool GetAllConnectedTargets();

		/// <summary>
		/// This will request the GameTalkServer to repeatedly send the given message
		/// to the list of given registered targets.
		/// </summary>
		/// <param name="message"></param>
		/// <param name="targetName"></param>
		/// <param name="frequency">In milliseconds</param>
		/// <returns></returns>
		bool StartSendingMessageToRegisteredTargets(GameTalkMessage message, string targetName, int frequency);

		/// <summary>
		/// This will request the GameTalkServer to stop sending the given message
		/// to the list of given registered targets.
		/// </summary>
		/// <param name="message"></param>
		/// <param name="targetName"></param>
		/// <returns></returns>
		bool StopSendingMessageToRegisteredTargets(GameTalkMessage message, string targetName);

		#endregion

		#region Identity getter accessors
		/// <summary>
		/// Returns the local version of GameTalk being used
		/// </summary>
		string ClientVersion
		{
			get;
		}

		/// <summary>
		/// Gets the this target's name
		/// </summary>
		string TargetName
		{
			get;
		}
		#endregion

		#region Synchronous messaging
		/// <summary>
		/// Used to register a user's Synchronous GameTalkMessage handler
		/// 
		/// We probably want to change the name-space/scope of SynchronousMessageReceivedDelegate
		/// to be in a class in IGameTalkInstance - but this will break existing users' code
		/// </summary>
		/// <param name="userCallback"></param>
		/// <param name="channel"></param>
		/// <returns></returns>
		bool RegisterSynchronousMessageHandler(GameTalkInstance.SynchronousMessageReceivedDelegate userCallback, string channel);

		/// <summary>
		/// User can unregister their synchronous GameTalkMessage handler
		/// </summary>
		/// <param name="synchroMessageHandler"></param>
		void UnregisterSynchronousMessageHandler(GameTalkInstance.SynchronousMessageReceivedDelegate synchroMessageHandler);

		/// <summary>
		/// This will send a synchronous message to the specified target
		/// </summary>
		/// <param name="target">recipient of the message</param>
		/// <param name="gameTalkMessage">message to send</param>
		/// <param name="numOfPolls">number of times to idle</param>
		/// <param name="idleTime">Time to idle in milliseconds</param>
		/// <returns></returns>
		GameTalkMessage SendSynchronousMessage(string target, 
			GameTalkMessage gameTalkMessage, int numOfPolls, int idleTime);
		#endregion

		#region Methods to facilitate single-threaded mode of GameTalk
		/// <summary>
		/// Returns the number of full GameTalkMessages that are available for processing
		/// </summary>
		/// <returns></returns>
		int Peek();

		/// <summary>
		/// Allows user to recurse into the processing of buffered data
		/// Avoid using this unless absolutely necessary - this has been added to address a very specific and unique user requirement
		/// There should be no reason to use this except within the context of a GameTalk callback/delegate
		/// </summary>
		void PollBufferedData();

		/// <summary>
		/// This can be used when operating in single-threaded mode
		/// </summary>
		void Poll();
		#endregion
	}
}
