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

namespace Apewer.Source
{

    /// <summary>表示此表拥有索引,此特性不被继承。</summary>
    [Serializable]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
    public sealed class IndexAttribute : Attribute
    {

        string _name = null;
        string _sql = null;

        /// <summary>索引名称。</summary>
        public string Name { get; }

        /// <summary>用于创建索引的 SQL 语句。</summary>
        public string SqlStatement { get; set; }

        /// <summary>声明索引。</summary>
        /// <param name="name">索引名称。</param>
        /// <param name="sqlStatement">用于创建此索引的 SQL 语句。</param>
        public IndexAttribute(string name, string sqlStatement)
        {
            _name = name.ToTrim();
            _sql = sqlStatement.ToTrim();
        }

        /// <summary>从 <see cref="IndexAttribute"/> 到 Boolean 的隐式转换,判断 <see cref="IndexAttribute"/> 有效。</summary>
        public static implicit operator bool(IndexAttribute instance)
        {
            if (instance == null) return false;
            if (instance._name.IsEmpty()) return false;
            if (instance._sql.IsEmpty()) return false;
            return true;
        }

        #region Parse & Cache

        private static Dictionary<string, IndexAttribute[]> _cache = new Dictionary<string, IndexAttribute[]>();

        /// <summary>解析索引特性,默认使用缓存以提升性能。</summary>
        public static IndexAttribute[] Parse<T>(bool useCache = true) where T : class, new() => Parse(typeof(T), useCache);

        /// <summary>解析索引特性,默认使用缓存以提升性能。</summary>
        public static IndexAttribute[] Parse(Type type, bool useCache = true)
        {
            if (type == null) return new IndexAttribute[0];
            var cacheKey = type.FullName;

            if (useCache)
            {
                lock (_cache)
                {
                    IndexAttribute[] cached;
                    if (_cache.TryGetValue(cacheKey, out cached)) return cached;
                }
            }

            var attributes = type.GetCustomAttributes(typeof(IndexAttribute), false);
            var list = new List<IndexAttribute>();
            foreach (var attribute in attributes)
            {
                var ia = attribute as IndexAttribute;
                if (!ia) continue;
                list.Add(ia);
            }

            var items = list.ToArray();
            if (useCache)
            {
                lock (_cache)
                {
                    if (_cache.ContainsKey(cacheKey)) _cache[cacheKey] = items;
                    else _cache.Add(cacheKey, items);
                }
            }

            return items;
        }

        #endregion

    }

}