/* Genuine Channels product.
 * 
 * Copyright (c) 2002-2007 Dmitry Belikov. All rights reserved.
 * 
 * This source code comes under and must be used and distributed according to the Genuine Channels license agreement.
 */

using System;
using System.Collections;
using System.Threading;

using Belikov.GenuineChannels.Connection;
using Belikov.GenuineChannels.DirectExchange;
using Belikov.GenuineChannels.Logbook;
using Belikov.GenuineChannels.Parameters;
using Belikov.GenuineChannels.Receiving;
using Belikov.GenuineChannels.Security;

using Belikov.GenuineChannels.GenuineSharedMemory;
using Belikov.GenuineChannels.GenuineTcp;
using Belikov.GenuineChannels.GenuineUdp;
using Belikov.GenuineChannels.GenuineHttp;

namespace Belikov.GenuineChannels.TransportContext
{
	/// <summary>
	/// Implements a transport context interface.
	/// </summary>
	internal class TransportContext : MarshalByRefObject, ITransportContext
	{
		/// <summary>
		/// To prevent creating Transport Contexts.
		/// </summary>
		internal TransportContext()
		{
			Guid guid = GenuineUtility.DefaultHostIdentifier;
			this._binaryHostIdentifier = guid.ToByteArray();
			this._hostIdentifier = guid.ToString("N");
		}

		/// <summary>
		/// To guarantee atomic access to local members.
		/// </summary>
		private object _accessToLocalMembers = new object();

		/// <summary>
		/// A set of key providers valid in this transport context.
		/// </summary>
		public IKeyStore IKeyStore
		{
			get
			{
				return _iKeyStore;
			}
		}
		internal IKeyStore _iKeyStore;

		/// <summary>
		/// A set of message senders providing a transport services for delivering messages
		/// to the remote host.
		/// </summary>
		public ConnectionManager ConnectionManager
		{
			get
			{
				return _connectionManager;
			}
		}
		internal ConnectionManager _connectionManager;

		/// <summary>
		/// The message processor that handles incoming messages.
		/// </summary>
		public IIncomingStreamHandler IIncomingStreamHandler 
		{ 
			get
			{
				return this._iIncomingStreamHandler;
			}
		}
		internal IIncomingStreamHandler _iIncomingStreamHandler;

		/// <summary>
		/// Direct Exchange Manager (DXM).
		/// </summary>
		public DirectExchangeManager DirectExchangeManager
		{
			get
			{
				return this._directExchangeManager;
			}
		}
		internal DirectExchangeManager _directExchangeManager;

		/// <summary>
		/// Host-specific information including URI, URL, Security Sessions and Client Sessions.
		/// </summary>
		public KnownHosts KnownHosts
		{
			get
			{
				return _knownHosts;
			}
		}
		internal KnownHosts _knownHosts;

		/// <summary>
		/// The identifier of this host to build a channel URI.
		/// </summary>
		public string HostIdentifier
		{ 
			get
			{
				return this._hostIdentifier;
			}
		}
		internal string _hostIdentifier;

		/// <summary>
		/// The identifier of this Transport Context represented by sequence of bytes.
		/// </summary>
		public byte[] BinaryHostIdentifier 
		{ 
			get
			{
				return this._binaryHostIdentifier;
			}
		}
		internal byte[] _binaryHostIdentifier;

		/// <summary>
		/// Transport parameters overriding default parameters but are overriden by channel parameters.
		/// </summary>
		public IParameterProvider IParameterProvider
		{ 
			get
			{
				return _iParameterProvider;
			}
		}
		internal IParameterProvider _iParameterProvider;

		/// <summary>
		/// Gets the event provider in the Transport Context.
		/// </summary>
		public IGenuineEventProvider IGenuineEventProvider
		{
			get
			{
				return _iGenuineEventProvider;
			}
		}
		internal IGenuineEventProvider _iGenuineEventProvider;

		/// <summary>
		/// Gets the logger which writes down all notices, warnings, errors and debug messages 
		/// generated by Genuine Channels.
		/// </summary>
		public BinaryLogWriter BinaryLogWriter
		{ 
			get
			{
				lock (this._accessToLocalMembers)
					return GenuineLoggingServices.BinaryLogWriter;
			}
			set
			{
				lock (this._accessToLocalMembers)
					GenuineLoggingServices.BinaryLogWriter = value;
			}
		}

		/// <summary>
		/// Gets or Sets the current security context being used on the channel level.
		/// </summary>
		public SecuritySessionParameters SecuritySessionParameters
		{ 
			get
			{
				lock(_securitySessionParametersLock)
				{
					return this._securitySessionParameters;
				}
			}
			set 
			{
				lock(_securitySessionParametersLock)
				{
					this._securitySessionParameters = value;
				}
			}
		}
		private SecuritySessionParameters _securitySessionParameters;
		private object _securitySessionParametersLock = new object();

		/// <summary>
		/// Security Session parameters that will be always ignored in this Transport Context.
		/// </summary>
		public SecuritySessionAttributes ProhibitedSecuritySessionAttributes
		{
			get
			{
				lock(_prohibitedSecuritySessionAttributesLock)
					return _prohibitedSecuritySessionAttributes;
			}
			set
			{
				lock(_prohibitedSecuritySessionAttributesLock)
					_prohibitedSecuritySessionAttributes = value;
			}
		}
		private SecuritySessionAttributes _prohibitedSecuritySessionAttributes = SecuritySessionAttributes.None;
		private object _prohibitedSecuritySessionAttributesLock = new object();

		/// <summary>
		/// Security Session parameters that will be forced for all invocations sent via this 
		/// channel if they're not prohibited by ProhibitedSecuritySessionParameters member.
		/// </summary>
		public SecuritySessionAttributes ForcedSecuritySessionAttributes
		{
			get
			{
				lock(_forcedSecuritySessionAttributesLock)
					return _forcedSecuritySessionAttributes;
			}
			set
			{
				lock(_forcedSecuritySessionAttributesLock)
					_forcedSecuritySessionAttributes = value;
			}
		}
		private SecuritySessionAttributes _forcedSecuritySessionAttributes = SecuritySessionAttributes.None;
		private object _forcedSecuritySessionAttributesLock = new object();

		/// <summary>
		/// Returns an instance of the SecuritySessionParameters class brought to conformity with channels' settings.
		/// </summary>
		/// <param name="securitySessionParameters">Source parameters.</param>
		/// <returns>Fixed parameters.</returns>
		public SecuritySessionParameters FixSecuritySessionParameters(SecuritySessionParameters securitySessionParameters)
		{
			SecuritySessionAttributes fixedAttributes = (SecuritySessionAttributes) (
				((int) securitySessionParameters.Attributes | (int) this.ForcedSecuritySessionAttributes)  & 
				~( (int) this.ProhibitedSecuritySessionAttributes) );

			return new SecuritySessionParameters(securitySessionParameters.Name, fixedAttributes, TimeSpan.MinValue, securitySessionParameters.GenuineConnectionType, securitySessionParameters.ConnectionName, TimeSpan.MinValue, securitySessionParameters.RemoteTransportUser);
		}

	}
}
