using System;
using System.Collections;
using System.Reflection;

namespace ChuPiao.Common.Enums
{
    /// <summary>
    /// 枚举描述类 
    /// 调用示例：EnumDescription[] arr = EnumDescription.GetFieldTexts(typeof(MachineType));
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)]
    public class EnumDescription : Attribute
    {
        private string _enumDisplayText;
        private int _enumRank;
        private FieldInfo _fieldInfo;

        /// <summary>        
        /// 描述枚举值        
        /// </summary>        
        /// <param name="enumDisplayText">描述内容</param>        
        /// <param name="enumRank">排列顺序</param>        
        public EnumDescription(string enumDisplayText, int enumRank)
        {
            this._enumDisplayText = enumDisplayText;
            this._enumRank = enumRank;
        }

        /// <summary>        
        ///  描述枚举值，默认排序为5        
        /// </summary>        
        /// <param name="enumDisplayText">描述内容</param>        
        public EnumDescription(string enumDisplayText) : this(enumDisplayText, 5)
        {
        }
        /// <summary>
        /// 枚举描述文本
        /// </summary>
        public string EnumDisplayText
        {
            get { return this._enumDisplayText; }
        }
        /// <summary>
        /// 枚举排序值
        /// </summary>
        public int EnumRank
        {
            get { return _enumRank; }
        }
        /// <summary>
        /// 枚举值
        /// </summary>
        public int EnumValue
        {
            get { return (int) _fieldInfo.GetValue(null); }    //null，是因为枚举没有像类一样可以有多个对象，即枚举不能也必要实例化
        }
        /// <summary>
        /// 枚举名称
        /// </summary>
        public string FieldName
        {
            get { return _fieldInfo.Name; }
        }

        public override string ToString()
        {
            return _enumDisplayText;
        }

        #region 对枚举描述属性的解释相关函数

        /// <summary>        
        /// 排序类型        
        /// </summary>        
        public enum SortType
        {
            /// <summary>            
            ///按枚举顺序默认排序            
            /// </summary>            
            Default,
            /// <summary>            
            /// 按描述值排序            
            /// </summary>            
            DisplayText,
            /// <summary>            
            /// 按排序熵            
            /// </summary>            
            Rank
        }

        private static Hashtable _cachedEnum = new Hashtable();

        /// <summary>        
        /// 得到对枚举的描述文本        
        /// </summary>        
        /// <param name="enumType">枚举类型</param>        
        /// <returns></returns>        
        public static string GetEnumText(Type enumType)
        {
            EnumDescription[] customAttributes = (EnumDescription[]) enumType.GetCustomAttributes(typeof (EnumDescription), false);
            if (customAttributes.Length != 1) return string.Empty;
            return customAttributes[0].EnumDisplayText;
        }

        /// <summary>        
        /// 获得指定枚举类型中，指定值的描述文本。        
        /// </summary>        
        /// <param name="enumValue">枚举值，不要作任何类型转换</param>        
        /// <returns>描述字符串</returns>        
        public static string GetFieldText(object enumValue)
        {
            EnumDescription[] descriptions = GetFieldTexts(enumValue.GetType(), SortType.Default);
            foreach (EnumDescription description in descriptions)
            {
                if (description._fieldInfo.Name == enumValue.ToString()) return description.EnumDisplayText;
            }
            return string.Empty;
        }

        /// <summary>        
        /// 得到枚举类型定义的所有文本，按定义的顺序返回        
        /// </summary>        
        /// <exception cref="NotSupportedException"></exception>        
        /// <param name="enumType">枚举类型</param>        
        /// <returns>所有定义的文本</returns>        
        public static EnumDescription[] GetFieldTexts(Type enumType)
        {
            return GetFieldTexts(enumType, SortType.Default);
        }

        /// <summary>        
        /// 得到枚举类型定义的所有文本        
        /// </summary>        
        /// <exception cref="NotSupportedException"></exception>        
        /// <param name="enumType">枚举类型</param>        
        /// <param name="sortType">指定排序类型</param>        
        /// <returns>所有定义的文本</returns>        
        public static EnumDescription[] GetFieldTexts(Type enumType, SortType sortType)
        {
            EnumDescription[] descriptions = null;
            
            //缓存中没有找到，通过反射获得字段的描述信息            
            if (_cachedEnum.Contains(enumType.FullName) == false)
            {
                FieldInfo[] fields = enumType.GetFields();
                ArrayList edAL = new ArrayList();
                foreach (FieldInfo fi in fields)
                {
                    object[] eds = fi.GetCustomAttributes(typeof(EnumDescription), false);  //GetCustomAttributes里面会调构造函数
                    if (eds.Length != 1) continue;
                    ((EnumDescription) eds[0])._fieldInfo = fi;
                    edAL.Add(eds[0]);
                }
                _cachedEnum.Add(enumType.FullName, (EnumDescription[]) edAL.ToArray(typeof (EnumDescription)));
            }
            descriptions = (EnumDescription[]) _cachedEnum[enumType.FullName];
            if (descriptions.Length <= 0)
                throw new NotSupportedException("枚举类型[" + enumType.Name + "]未定义属性EnumValueDescription");
            //按指定的属性冒泡排序            
            for (int m = 0; m < descriptions.Length; m++)
            {
                //默认就不排序了                
                if (sortType == SortType.Default) break;
                for (int n = m; n < descriptions.Length; n++)
                {
                    EnumDescription temp;
                    bool swap = false;
                    switch (sortType)
                    {
                        case SortType.Default:
                            break;
                        case SortType.DisplayText:
                            if (string.Compare(descriptions[m].EnumDisplayText, descriptions[n].EnumDisplayText) > 0)
                                swap = true;
                            break;
                        case SortType.Rank:
                            if (descriptions[m].EnumRank > descriptions[n].EnumRank) swap = true;
                            break;
                    }
                    if (swap)
                    {
                        temp = descriptions[m];
                        descriptions[m] = descriptions[n];
                        descriptions[n] = temp;
                    }
                }
            }
            return descriptions;
        }

        #endregion
    }
}