using Apewer;
using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Data;

namespace Apewer.Source
{

    /// <summary>查询数据表。</summary>
    public class Query : IQuery, IDisposable
    {

        private bool _disposed = false;
        private bool _success = false;
        private string _error = "";
        private string _message = "";
        private Exception _exception = null;
        private List<DataTable> _tables = new List<DataTable>();

        #region Property

        /// <summary>语句执行成功。</summary>
        public bool Success
        {
            get
            {
                if (_disposed) return false;
                return _success;
            }
            set
            {
                if (_disposed) return;
                _success = value;
            }
        }

        /// <summary>错误信息。</summary>
        public string Error
        {
            get
            {
                if (_disposed) return "";
                if (!string.IsNullOrEmpty(_error)) return _error;
                if (_exception == null) return "";
                var error = "";
                try { error = _exception.Message; } finally { }
                return error;
            }
            set
            {
                if (_disposed) return;
                _error = value ?? "";
            }
        }

        /// <summary>消息。</summary>
        public string Message
        {
            get
            {
                if (_disposed) return "";
                return _message ?? "";
            }
            set
            {
                if (_disposed) return;
                _message = value ?? "";
            }
        }

        /// <summary>语句执行失败时的 Exception 对象。</summary>
        public Exception Exception
        {
            get { if (_disposed) return null; return _exception; }
            set { if (_disposed) return; _exception = value; }
        }

        /// <summary>所有结果表。</summary>
        public List<DataTable> Tables
        {
            get { if (_disposed) return new List<DataTable>(); return _tables; }
        }

        /// <summary>获取默认结果表。如果设置默认结果表,会丢失设置前的所有结果表。</summary>
        public DataTable Table
        {
            get
            {
                if (_disposed) return null;
                if (_tables.Count < 1) return null;
                return _tables[0];
            }
            set
            {
                if (_disposed) return;
                Clear();
                if (_disposed) return;
                _tables.Add(value);
            }
        }

        /// <summary>所有表中不含内容行。</summary>
        public bool Empty
        {
            get
            {
                if (_disposed) return true;
                if (_tables.Count < 1) return true;
                foreach (var table in _tables)
                {
                    if (table == null) continue;
                    try
                    {
                        if (table.Rows.Count > 0) return false;
                    }
                    finally { }
                }
                return true;
            }
        }

        /// <summary>默认表中的数据总行数。</summary>
        public int Rows
        {
            get
            {
                if (_disposed) return 0;
                if (Table != null) return Table.Rows.Count;
                else return 0;
            }
        }

        /// <summary>默认表中的数据总列数。</summary>
        public int Columns
        {
            get
            {
                if (_disposed) return 0;
                if (Table != null) return Table.Columns.Count;
                else return 0;
            }
        }

        #endregion

        #region Text

        private string Text(object value)
        {
            var result = Constant.EmptyString;
            if (value != null)
            {
                if (!value.Equals(DBNull.Value))
                {
                    try
                    {
                        result = value.ToString();
                    }
                    finally { }
                }
            }
            return result;
        }

        /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
        public string Text()
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value();
            return Text(value);
        }

        /// <summary>获取默认表中指定行中第 0 列的内容。</summary>
        /// <param name="rowIndex">行索引,从 0 开始。</param>
        public string Text(int rowIndex)
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value(rowIndex);
            return Text(value);
        }

        /// <summary>获取默认表中第 0 行指定列的内容。</summary>
        /// <param name="columnName">列名称。</param>
        public string Text(string columnName)
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value(columnName);
            return Text(value);
        }

        /// <summary>获取默认表中指定单元格的内容。</summary>
        /// <param name="rowIndex">行索引,从 0 开始。</param>
        /// <param name="columnIndex">列索引,从 0 开始。</param>
        public string Text(int rowIndex, int columnIndex)
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value(rowIndex, columnIndex);
            return Text(value);
        }

        /// <summary>获取默认表中指定单元的内容。</summary>
        /// <param name="rowIndex">行索引,从 0 开始。</param>
        /// <param name="columnName">列名称。</param>
        public string Text(int rowIndex, string columnName)
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value(rowIndex, columnName);
            return Text(value);
        }

        /// <summary>搜索默认表。</summary>
        /// <param name="conditionColumn">搜索条件:列名。</param>
        /// <param name="conditionValue">搜索条件:列值。</param>
        /// <param name="resultColumn">搜索结果。</param>
        public string Text(string conditionColumn, string conditionValue, string resultColumn)
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value(conditionColumn, conditionValue, resultColumn);
            return Text(value);
        }

        /// <summary>搜索默认表。</summary>
        /// <param name="conditionColumn">搜索条件:列名。</param>
        /// <param name="conditionValue">搜索条件:列值。</param>
        /// <param name="resultColumn">搜索结果。</param>
        public string Text(int conditionColumn, string conditionValue, int resultColumn)
        {
            if (_disposed) return Constant.EmptyString;
            var value = Value(conditionColumn, conditionValue, resultColumn);
            return Text(value);
        }

        #endregion

        #region Value

        /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
        public object Value()
        {
            if (_disposed) return null;
            return Value(0, 0);
        }

        /// <summary>获取默认表中指定行中第 0 列的内容。</summary>
        /// <param name="rowIndex">行索引,从 0 开始。</param>
        public object Value(int rowIndex)
        {
            if (_disposed) return null;
            return Value(rowIndex, 0);
        }

        /// <summary>获取默认表中第 0 行指定列的内容。</summary>
        /// <param name="columnName">列名称。</param>
        public object Value(string columnName)
        {
            if (_disposed) return null;
            return Value(0, columnName);
        }

        /// <summary>获取默认表中指定单元格的内容。</summary>
        /// <param name="rowIndex">行索引,从 0 开始。</param>
        /// <param name="columnIndex">列索引,从 0 开始。</param>
        public object Value(int rowIndex, int columnIndex)
        {
            if (_disposed) return null;
            if (Table != null)
            {
                if (rowIndex >= 0 && rowIndex < Table.Rows.Count)
                {
                    if (columnIndex >= 0 && columnIndex < Table.Columns.Count)
                    {
                        return Table.Rows[rowIndex][columnIndex];
                    }
                }
            }
            return null;
        }

        /// <summary>获取默认表中指定单元的内容。</summary>
        /// <param name="rowIndex">行索引,从 0 开始。</param>
        /// <param name="columnName">列名称。</param>
        public object Value(int rowIndex, string columnName)
        {
            if (_disposed) return null;
            if ((Table != null) && !string.IsNullOrEmpty(columnName))
            {
                if ((rowIndex < Table.Rows.Count) && (rowIndex >= 0))
                {
                    try { return Table.Rows[rowIndex][columnName]; }
                    catch { }
                }
            }
            return null;
        }

        /// <summary>搜索默认表。</summary>
        /// <param name="conditionColumn">搜索条件:列名。</param>
        /// <param name="conditionValue">搜索条件:列值。</param>
        /// <param name="resultColumn">搜索结果。</param>
        public object Value(string conditionColumn, string conditionValue, string resultColumn)
        {
            if (_disposed) return null;
            if ((Table != null) && (!string.IsNullOrEmpty(conditionColumn)) && (conditionValue != null) && (!string.IsNullOrEmpty(resultColumn)))
            {
                for (int i = 0; i < Table.Rows.Count; i++)
                {
                    try
                    {
                        if (Table.Rows[i][conditionColumn].ToString() == conditionValue) return Table.Rows[i][resultColumn];
                    }
                    catch { }
                }
            }
            return null;
        }

        /// <summary>搜索默认表。</summary>
        /// <param name="conditionColumn">搜索条件:列名。</param>
        /// <param name="conditionValue">搜索条件:列值。</param>
        /// <param name="resultColumn">搜索结果。</param>
        public object Value(int conditionColumn, string conditionValue, int resultColumn)
        {
            if (_disposed) return null;
            if ((Table != null) && (conditionColumn >= 0) && (conditionValue != null) && (resultColumn >= 0))
            {
                if ((conditionColumn < Table.Columns.Count) && (resultColumn < Table.Columns.Count))
                {
                    for (int i = 0; i < Table.Rows.Count; i++)
                    {
                        try
                        {
                            if (Table.Rows[i][conditionColumn].ToString() == conditionValue) return Table.Rows[i][resultColumn];
                        }
                        catch { }
                    }
                }
            }
            return null;
        }

        #endregion

        #region Method

        /// <summary>拆分表组,单独查询。</summary>
        public List<Query> Split()
        {
            var list = new List<Query>();
            if (_disposed) return list;
            foreach (var table in _tables)
            {
                if (table == null) continue;
                var query = new Query();
                query._success = true;
                query._tables.Add(table);
                list.Add(query);
            }
            return list;
        }

        /// <summary>添加数据表。</summary>
        public bool Add(DataTable tables)
        {
            if (_disposed) return false;
            if (tables == null) return false;
            _tables.Add(tables);
            return true;
        }

        /// <summary>添加数据表。</summary>
        public int Add(IEnumerable<DataTable> tables)
        {
            var count = 0;
            if (_disposed) return count;
            if (tables == null) return count;
            foreach (var table in tables)
            {
                if (table == null) continue;
                _tables.Add(table);
                count = count + 1;
            }
            return count;
        }

        /// <summary>清除所有表,并释放系统资源。</summary>
        public virtual void Clear()
        {
            if (_tables != null)
            {
                foreach (var table in _tables)
                {
                    if (table != null)
                    {
                        try { table.Dispose(); } catch { }
                    }
                }
                _tables.Clear();
            }
            if (_exception != null) _exception = null;
            _success = false;
        }

        /// <summary>释放系统资源。</summary>
        public virtual void Dispose()
        {
            Clear();
            _disposed = true;
            // GC.SuppressFinalize(this);
        }

        /// <summary></summary>
        /// <exception cref="Exception"></exception>
        public List<T> Fill<T>() where T : Record
        {
            var list = new List<T>();
            var type = typeof(T);
            for (int r = 0; r < Rows; r++)
            {
                var entity = type.Assembly.CreateInstance(type.FullName);

                var ts = TableStructure.ParseModel(type);
                var properties = type.GetProperties();
                foreach (var property in properties)
                {
                    if (ts.Columns.ContainsKey(property.Name) == false) continue;

                    var setter = property.GetSetMethod();
                    if (setter == null) continue;

                    var attribute = ts.Columns[property.Name];
                    var pt = property.PropertyType;

                    if (pt.Equals(typeof(object)) || pt.Equals(typeof(Nullable<DateTime>)))
                    {
                        setter.Invoke(entity, new object[] { Value(r, attribute.Field) });
                    }
                    else if (pt.Equals(typeof(DateTime)))
                    {
                        var value = Value(r, attribute.Field);
                        if (value != null) setter.Invoke(entity, new object[] { Value(r, attribute.Field) });
                    }
                    else if (pt.Equals(typeof(byte[])))
                    {
                        setter.Invoke(entity, new object[] { (byte[])Value(r, attribute.Field) });
                    }
                    else if (pt.Equals(typeof(byte)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetByte(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(sbyte)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetSByte(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(short)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetInt16(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(ushort)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetUInt16(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(int)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetInt32(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(uint)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetUInt32(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(long)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetInt64(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(ulong)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetUInt64(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(float)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetSingle(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(double)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetDouble(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(decimal)))
                    {
                        setter.Invoke(entity, new object[] { TextConverter.GetDecimal(Text(r, attribute.Field)) });
                    }
                    else if (pt.Equals(typeof(string)))
                    {
                        setter.Invoke(entity, new object[] { Text(r, attribute.Field) });
                    }
                    else
                    {
                        try
                        {
                            setter.Invoke(entity, new object[] { Value(r, attribute.Field) });
                        }
                        catch { }
                    }
                }
                list.Add((T)entity);
            }
            return list;
        }

        #endregion

        #region Static

        private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } }

        /// <summary>简单查询:取结果中第 0 列所有单元格的文本形式,可指定查询后关闭服务器连接,返回结果中不包含无效文本。</summary>
        public static List<string> SimpleColumn(IDatabase database, string statement, bool close = false)
        {
            var list = new List<string>();
            if (database == null) return list;
            if (!database.Connect()) return list;
            var query = database.Query(statement);
            for (int i = 0; i < query.Rows; i++)
            {
                var cell = TextModifier.Trim(query.Text(i));
                if (string.IsNullOrEmpty(cell)) continue;
                if (list.Contains(cell)) continue; ;
                list.Add(cell);
            }
            query.Dispose();
            if (close) database.Close();
            return list;
        }

        /// <summary>简单查询:取结果中第 0 行、第 0 列单元格中的文本,可指定查询后关闭服务器连接。</summary>
        public static string SimpleCell(IDatabase database, string statement, bool close = false)
        {
            if (database == null) return "";
            if (!database.Connect()) return "";
            var vquery = database.Query(statement);
            var vcell = TextModifier.Trim(vquery.Text());
            vquery.Dispose();
            if (close) database.Close();
            return vcell;
        }

        #endregion

    }

}