#if SQLSERVER
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace Sdaleo.Systems.SQLServer
{
    /// <summary>
    /// Handles SQL Server Credentials, to be
    /// used by all our SQL Server Functions
    /// </summary>
    public class SQLServerCredential : IComparable, ICloneable, IConnectDb, IamDBMS, IsupportTimeouts, IClearConnectionPool
    {
        #region IConnectDb

        /// <summary>
        /// Let Callers know this is a SQL Server Connection Object
        /// </summary>
        public DBSystem DBType { get { return DBSystem.SQL_SERVER; } }

        /// <summary>
        /// Check to see if the Credential Object consists of valid input
        /// </summary>
        public bool IsValid
        {
            get
            {
                if (!Validation.IsValidDataSource(_UDL.DataSource))
                    return false;

                if (!_UDL.TrustedConnection && !ValidationConsts.Generic.IsValidUserCredential(_UDL.Username, _UDL.Password))
                    return false;

                if (!String.IsNullOrEmpty(_UDL.DataBase) && !IsDatabaseSet)
                    return false;

                return true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public string ConnectionString { get { return _UDL.ConnectionString; } }

        /// <summary>
        /// SQL Server uses Server N' Instance
        /// </summary>
        public string DataSource { get { return _UDL.DataSource; } }

        /// <summary>
        /// SQL Server requires a user
        /// </summary>
        public string User { get { return _UDL.Username; } }

        /// <summary>
        /// SQL Server supports is a DBMS
        /// </summary>
        public bool SupportsDBMS { get { return true; } }

        /// <summary>
        /// SQL Server is a DBMS
        /// </summary>
        public IamDBMS DBMS { get { return this; } }

        /// <summary>
        /// SQL Server supports Timeouts
        /// </summary>
        public bool SupportsTimeouts { get { return true; } }

        /// <summary>
        /// SQL Server supports Timeouts
        /// </summary>
        public IsupportTimeouts Timeouts { get { return this; } }

        #endregion

        private UDL _UDL = null;

        #region SQL Server Credential Constructors

        /// <summary>
        /// Create a SQL Server Connection from an UDL Object
        /// </summary>
        /// <param name="udl"></param>
        internal SQLServerCredential(UDL udl)
        {
            if (udl != null)
                _UDL = udl;
        }
        
        /// <summary>
        /// Create an Untrusted SQLServer Credential with an Initial DB Specified
        /// </summary>
        public SQLServerCredential(string strServer, string strInstance, string strDatabase, string strUser, string strPassword)
        {
            _UDL = new UDL(strDatabase, strUser, strPassword, strServer, strInstance);
        }

        /// <summary>
        /// Create an Untrusted SQLServer Credential with no Initial DB Specified
        /// </summary>
        public SQLServerCredential(string strServer, string strInstance, string strUser, string strPassword)
        {
            _UDL = new UDL(String.Empty, strUser, strPassword, strServer, strInstance);
        }                

        /// <summary>
        /// Create a Trusted SQLServer Credential with an Initial DB Specified
        /// </summary>
        public SQLServerCredential(string strServer, string strInstance, string strDatabase)
        {
            _UDL = new UDL(strDatabase, String.Empty, String.Empty, strServer, strInstance, true);
        }

        /// <summary>
        /// Create a Trusted SQLServer Credential with no Initial DB Specified
        /// </summary>
        public SQLServerCredential(string strServer, string strInstance)
        {
            _UDL = new UDL(String.Empty, String.Empty, String.Empty, strServer, strInstance, true);            
        }

        /// <summary>
        /// Create a Trusted SQLServer Credential with SQLExpress on the Local Machine to Attach a DB File (Creates a User Instance)
        /// </summary>
        /// <param name="strAttachDBFile"></param>
        public SQLServerCredential(string strAttachSQLDBFile)
        {
            _UDL = new UDL(String.Empty, String.Empty, String.Empty, String.Empty, "SQLEXPRESS", strAttachSQLDBFile, true, false);
        }

        #endregion

        #region IamDBMS

        public string Server { get { return _UDL.ServerAddress; } }
        public string Instance { get { return _UDL.InstanceName; } }
        public string Database { get { return _UDL.DataBase; } }

        public bool IsDatabaseSet
        { 
            get 
            { 
                DBError dbError = Validation.IsValidDatabaseName(Database);
                return !dbError.ErrorOccured;
            } 
        }

        public bool IsDatabaseSetAndNonSystem
        {
            get
            {
                if (IsDatabaseSet && !SQLServerUtilities.IsSystemDatabaseName(Database))
                    return true;
                return false;
            }
        }

        public bool IsDatabaseSetAndNonDefault
        {
            get
            {
                if (IsDatabaseSet && !SQLServerUtilities.IsDefaultDatabaseName(Database))
                    return true;
                return false;
            }
        }   

        /// <summary>
        /// Use this to quickly create a new SQLServerCredential with a different DatabaseName
        /// </summary>
        /// <param name="strDatabaseName">Name of Database To Set</param>
        /// <returns>a new SQLServerCredential Object</returns>
        public IConnectDb WithDatabase(string strDatabaseName)
        {
            // Create a new Credential Object and change the DatabaseName
            SQLServerCredential credential = (SQLServerCredential)Clone();
            credential._UDL.DataBase = strDatabaseName;
            return credential;            
        }

        /// <summary>
        /// Use this to quickly create a new SQLServerCredential with no DatabaseName defined
        /// </summary>
        /// <returns>a new SQLServerCredential Object</returns>
        public IConnectDb WithoutDatabase()
        {
            return WithDatabase(String.Empty);
        }

        #endregion

        #region IsupportTimeouts

        public const int DEFAULT_COMMAND_TIMEOUT = 45;        
        private uint _CommandTimeout = DEFAULT_COMMAND_TIMEOUT;
        public uint CommandTimeout
        {
            get { return _CommandTimeout; }
            set { _CommandTimeout = value; }
        }

        public uint ConnectionTimeout { get { return _UDL.ConnectionTimeout; } set { _UDL.ConnectionTimeout = value; } }
        
        /// <summary>
        /// Use this to quickly create a new SQLServerCredential with a different connection timeout
        /// </summary>        
        /// <param name="nConnectionTimeout">Specify the Connection Timeout</param>      
        /// <returns>a new SQLServerCredential Object</returns>
        public IConnectDb WithConnectionTimeout(uint nConnectionTimeout)
        {
            // Create a new Credential Object and change the Timeouts
            SQLServerCredential credential = (SQLServerCredential)Clone();
            credential.ConnectionTimeout = nConnectionTimeout;
            return credential;
        }

        /// <summary>
        /// Use this to quickly create a new SQLServerCredential with a different command timeout
        /// </summary>        
        /// <param name="nCommandTimeout">Specify the Command Timeout</param>      
        /// <returns>a new SQLServerCredential Object</returns>
        public IConnectDb WithCommandTimeout(uint nCommandTimeout)
        {
            // Create a new Credential Object and change the Timeouts
            SQLServerCredential credential = (SQLServerCredential)Clone();
            credential.CommandTimeout = nCommandTimeout;
            return credential;
        }

        /// <summary>
        /// Use this to quickly create a new SQLServerCredential with different Timeouts
        /// </summary>
        /// <param name="nConnectionTimeout">Specify the Connection Timeout</param>
        /// <param name="nCommandTimeout">Specify the Command Timeout</param>      
        /// <returns>a new SQLServerCredential Object</returns>
        public IConnectDb WithTimeouts(uint nConnectionTimeout, uint nCommandTimeout)
        {
            // Create a new Credential Object and change the Timeouts
            SQLServerCredential credential = (SQLServerCredential)Clone();
            credential.ConnectionTimeout = nConnectionTimeout;
            credential.CommandTimeout = nCommandTimeout;
            return credential;
        }

        #endregion                                                   

        #region ICloneable Members

        public object Clone()
        {
            SQLServerCredential credential = new SQLServerCredential((UDL)this._UDL.Clone());
            credential.CommandTimeout = this.CommandTimeout;
            return credential;
        }

        #endregion

        #region IComparable Members

        public int CompareTo(object obj)
        {
            SQLServerCredential otherCredential = obj as SQLServerCredential;
            if (otherCredential != null)
            {
                int nCompare = _UDL.CompareTo(otherCredential._UDL);
                return nCompare;
            }
            else
            {
                throw new ArgumentException("Object is not a SQLServerCredential");
            }
        }

        #endregion

        #region IClearConnectionPool Members

        public void ClearConnectionPool(IConnectDb credential)
        {
            SqlConnection cn = new SqlConnection(credential.ConnectionString);
            SqlConnection.ClearPool(cn);            
        }

        #endregion
    }

}
#endif