using NHibernate.Dialect;
using NHibernate.Driver;

namespace FluentNHibernate.Cfg
{
    public class OracleConfiguration : PersistenceConfiguration<OracleConfiguration>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="OracleConfiguration"/> class using the
        /// Oracle Data Provider (Oracle.DataAccess) library.
        /// </summary>
        protected OracleConfiguration()
        {
            Driver<OracleDataClientDriver>();
        }

        public static OracleConfiguration Oracle9
        {
            get { return new OracleConfiguration().Dialect<Oracle9Dialect>(); }
        }

        public new OracleConnectionStringExpression ConnectionString
        {
            get
            {
                return new OracleConnectionStringExpression(this);
            }
        }

        public class OracleConnectionStringExpression : ConnectionStringExpression<OracleConfiguration>
        {
            private string _server;
            private string _instance;
            private string _username;
            private string _password;
            private int _port;
            private string _otherOptions;

            public OracleConnectionStringExpression(OracleConfiguration config)
                : base(config)
            {
            }

            public OracleConnectionStringExpression Server(string server)
            {
                _server = server;
                return this;
            }

            public OracleConnectionStringExpression Instance(string instance)
            {
                _instance = instance;
                return this;
            }

            public OracleConnectionStringExpression Username(string username)
            {
                _username = username;
                return this;
            }

            public OracleConnectionStringExpression Password(string password)
            {
                _password = password;
                return this;
            }

            public OracleConnectionStringExpression Port(int port)
            {
                _port = port;
                return this;
            }

            public OracleConnectionStringExpression OtherOptions(string otherOptions)
            {
                _otherOptions = otherOptions;
                return this;
            }

            public OracleConfiguration Create
            {
                get
                {
                    var builder = new OracleConnectionStringBuilder
                                      {
                                          Server = _server,
                                          Instance = _instance,
                                          Port = _port,
                                          UserID = _username,
                                          Password = _password
                                      };
                    
                    return _config.Raw(ConnectionStringKey, builder.ToString());
                }
            }
        }
    }

    internal class OracleConnectionStringBuilder
    {
        public string Server;
        public string Instance;
        public int Port;
        public string UserID;
        public string Password;
        public string OtherOptions;

        public override string ToString()
        {
            return
                string.Format(
                    @"  User Id={0};Password={1};{5}
                        Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={2})(PORT={3})))(CONNECT_DATA=(SERVICE_NAME={4})))", UserID, Password, Server, Port, Instance, OtherOptions);
        }
    }
}