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

using System.Data;
using System.Data.Common;
using System.Data.SqlClient;

namespace MyKarte.Database
{
    /// <summary>
    /// SQL Server クラス
    /// </summary>
    public sealed class SqlServer : DbBase
    {
        // ローカルホスト
        private const string _localHost = "(local)\\SQLEXPRESS";

        // ユーザID(デフォルト)
        private const string _defaultUserId = "sa";

        // パスワード(デフォルト)
        private const string _defaultPassword = null;

        // ホスト名
        private string _host;

        // データベース名
        private string _dbName;

        // ユーザID
        private string _userId;

        // パスワード
        private string _password;

        // 接続プール
        private bool _pooling;

        #region プロパティ
        /// <summary>
        /// ローカルホスト
        /// </summary>
        public static string LocalHost
        {
            get
            {
                return _localHost;
            }
        }

        /// <summary>
        /// ユーザID(デフォルト)
        /// </summary>
        public static string DefaultUserId
        {
            get
            {
                return _defaultUserId;
            }
        }

        /// <summary>
        /// パスワード(デフォルト)
        /// </summary>
        public static string DefaultPassword
        {
            get
            {
                return _defaultPassword;
            }
        }
        #endregion

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="host">ホスト名</param>
        /// <param name="dbName">データベース名</param>
        public SqlServer(string host, string dbName)
            : this(host, dbName, _defaultUserId, _defaultPassword, true)
        {
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="host">ホスト名</param>
        /// <param name="dbName">データベース名</param>
        /// <param name="pooling">接続プール</param>
        public SqlServer(string host, string dbName, bool pooling)
            : this(host, dbName, _defaultUserId, _defaultPassword, pooling)
        {
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="host">ホスト名</param>
        /// <param name="dbName">データベース名</param>
        /// <param name="userId">ユーザID</param>
        /// <param name="password">パスワード</param>
        public SqlServer(string host, string dbName, string userId, string password)
            : this(host, dbName, userId, password, true)
        {
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="host">ホスト名</param>
        /// <param name="dbName">データベース名</param>
        /// <param name="userId">ユーザID</param>
        /// <param name="password">パスワード</param>
        /// <param name="pooling">接続プール</param>
        public SqlServer(string host, string dbName, string userId, string password, bool pooling)
        {
            _host = host;
            _dbName = dbName;

            _userId = userId;
            _password = password;

            _pooling = pooling;

            this.Connection = CreateConnection();
            this.Connection.ConnectionString = GetConnectionString();
        }

        /// <summary>
        /// DbProviderFactoryを取得する。
        /// </summary>
        /// <returns>DbProviderFactory</returns>
        protected override DbProviderFactory GetFactory()
        {
            return DbProviderFactories.GetFactory("System.Data.SqlClient");
        }

        /// <summary>
        /// 接続文字列を取得する。
        /// </summary>
        /// <returns>接続文字列</returns>
        protected override string GetConnectionString()
        {
            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

            builder.DataSource = _host;
            builder.InitialCatalog = _dbName;

            // SQL Server認証
            builder.UserID = _userId;
            builder.Password = _password;

            // 接続プール
            builder.Pooling = _pooling;

            return builder.ConnectionString;
        }

        /// <summary>
        /// テーブル一覧を取得する。
        /// </summary>
        /// <returns>テーブル一覧</returns>
        public override string[] GetTables()
        {
            List<string> tables = new List<string>();

            StringBuilder sb = new StringBuilder();

            sb.Append("SELECT o.name");
            sb.Append("  FROM sysobjects o INNER JOIN sysindexes i ON o.id = i.id");
            sb.Append(" WHERE o.xtype = 'U'");
            sb.Append("   AND i.indid < 2");
            sb.Append(" ORDER BY o.name");

            DataTable dt = GetDataTable(sb.ToString());

            foreach (DataRow dr in dt.Rows)
            {
                tables.Add(Convert.ToString(dr["name"]));
            }

            return tables.ToArray();
        }
    }
}
