using System;
using System.Diagnostics;
using System.Text;
using System.IO;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
using System.Timers;
using IndianHealthService.BMXNet.Services;
using IndianHealthService.BMXNet.Model;

namespace IndianHealthService.BMXNet.Net
{
	/// <summary>
	/// BMXNetBroker implements low-level socket connectivity to RPMS databases.
	/// The VA RPC Broker must be running on the RPMS server in order for 
	/// BMXNetBroker to connect.
	/// </summary>

    [DnsPermission(SecurityAction.Assert, Unrestricted = true)]
    internal class BMXNetSocketBroker : BMXNetBroker, BMXNetSessionConnectionSource
    {
        public BMXNetSocketBroker()
        {            
        }

        private BMXRemoteSessionPool _sessionPool = null;

        internal BMXRemoteSessionPool SessionPool
        {
            get { return _sessionPool; }
            set { _sessionPool = value; }
        }

        public override RemoteSessionPool RemoteSessionPool
        {
            get { return this.SessionPool; }
        }

        public override void Close()
        {
            if (this.SessionPool != null)
            {
                this.SessionPool.Close();
                this.SessionPool = null;
            }
        }

        public User FriendUser
        {
            set
            {
                this.User = value;
            }
        }

        private bool _loggedInWithWindowsIdentity = false;

        public bool LoggedInWithWindowsIdentity
        {
            get { return _loggedInWithWindowsIdentity; }
            set { _loggedInWithWindowsIdentity = value; }
        }

        private BMXNetSocketConnectionSpec _connectionSpec = null;

        public BMXNetSocketConnectionSpec ConnectionSpec
        {
            get { return _connectionSpec; }
            set { _connectionSpec = value; }
        }


        public override bool IsConnected
        {
            get
            {
                return this.PrimarySession != null && this.PrimarySession.SessionConnection.IsConnected;
            }
        }


        public override RemoteSession PrimaryRemoteSession
        {
            get
            {
                return (RemoteSession)this.PrimarySession;
            }
        }

        private BMXNetRemoteSession _primarySession = null;

        internal BMXNetRemoteSession PrimarySession
        {
            get { return _primarySession; }
            set { _primarySession = value; }
        }


        void BMXNetSessionConnectionSource.CloseConnection(BMXNetSessionConnection aConnection)
        {
            if (aConnection == null)
            {
                return;
            }

            this.Log.Log("BMX NET", "Debug", "Closing Socket Session Connection");
            
            aConnection.Close();
        }


        BMXNetSessionConnection BMXNetSessionConnectionSource.OpenConnection()
        {
            this.Log.Log("BMX NET", "Debug", "Opening Socket Session Connection");
            BMXNetSessionSocketConnection connection = new BMXNetSessionSocketConnection(this);

            connection.OpenConnection(this.ConnectionSpec);

            return connection.IsConnected ? connection : null;
        }


        public override bool Open(string aServer, int aPort, string aNameSpace, string anAccessCode, string aVerifyCode,int sendTimeout,int receiveTimeout)
        {
            BMXNetSocketConnectionSpec spec = new BMXNetSocketConnectionSpec();
            spec.SendTimeout = sendTimeout;
            spec.ReceiveTimeout = receiveTimeout;
            spec.Server = aServer;
            spec.Port = aPort;
            spec.NameSpace = aNameSpace;
            spec.EncryptedAccessVerifyCode = new BMXNetSessionSocketConnection(this).EncryptAccessVerifyCode(anAccessCode, aVerifyCode);

            this.ConnectionSpec = spec;

            return this.Open(spec);
        }


        public override bool Open(string aServer, int aPort, string aNameSpace, WindowsIdentity windowsIdentity, int sendTimeout, int receiveTimeout)
        {
            BMXNetSocketConnectionSpec spec = new BMXNetSocketConnectionSpec();
            spec.SendTimeout = sendTimeout;
            spec.ReceiveTimeout = receiveTimeout;
            spec.Server = aServer;
            spec.Port = aPort;
            spec.NameSpace = aNameSpace;
            spec.WindowsIdentity = windowsIdentity;

            this.ConnectionSpec = spec;

            return this.Open(spec);
        }


        private bool Open(BMXNetSocketConnectionSpec aSpec)
        {
            this.ConnectionSpec = aSpec;
            this.SessionPool = new BMXRemoteSessionPool();
            this.SessionPool.Log = this.Log;
            this.SessionPool.Begin(this);
            this.PrimarySession = (BMXNetRemoteSession)this.SessionPool.OpenSession();

            return this.PrimarySession != null;
        }

        public override String RegisterWindowsIdentityForWindowsAuthenication(WindowsIdentity aWindowsIdentity)
        {
            if (this.PrimarySession.IsConnected)
            {
                if (aWindowsIdentity.IsAuthenticated)
                {
                    return this.PrimarySession.TransmitRPC("BMXNetSetUser", aWindowsIdentity.Name);
                }
                else
                {
                    throw new BMXNetException("Current Windows User is not authenticated");
                }
            }
            else
            {
                throw new BMXNetException("Connection disconnected immediately after login.");
            }
        }

   
    }
  
    /*
1 ;;1;Signons not currently allowed on this processor.
2 ;;1;Maximum number of users already signed on to this processor.
3 ;;1;This device has not been defined to the system -- contact system manager.
4 ;;0;Not a valid Windows Identity map value.
5 ;;0;No Access Allowed for this User.
6 ;;0;Invalid device password.
7 ;;0;Device locked due to too many invalid sign-on attempts.
8 ;;1;This device is out of service.
9 ;;0;*** MULTIPLE SIGN-ONS NOT ALLOWED ***
10 ;;1;You don't have access to this device!
11 ;;0;Your access code has been terminated. Please see your site manager!
12 ;;0;VERIFY CODE MUST be changed before continued use.
13 ;;1;This device may only be used outside of this time frame |
14 ;;0;'|' is not a valid UCI!
15 ;;0;'|' is not a valid program name!
16 ;;0;No PRIMARY MENU assigned to user or User is missing KEY to menu!
17 ;;0;Your access to the system is prohibited from |.
18 ;;0;Windows Integrated Security Not Allowed on this port.*/


}
