using System;

using System.Collections.Generic;
using System.Diagnostics;

namespace Wayne.Lib
{
    /// <summary>
    /// Enumsupport is a class that has the goal to provide the functionality offered by System.Enum class, but that 
    /// are not available in compact framework. It is very limited in some aspects, so please read carefully the comments of each method.
    /// </summary>
    public static class EnumSupport
    {
        /// <summary>
        /// Gets a list of the enumerated value names for the specified enumeration type.
        /// NOTE: The enum must not have explicit values set, so there are gaps in the value range, it must start at 0 and go up to max.
        /// </summary>
        /// <typeparam name="TEnumType"></typeparam>
        /// <returns></returns>
        public static string[] GetNames<TEnumType>()
        {
            Type type = typeof(TEnumType);

            if (!type.IsEnum)
                throw new ArgumentException("Type must be an enumeration.");

            List<string> names = new List<string>();

            int i = 0;
            while (System.Enum.IsDefined(type, i))
            {
                object oInt = i;
                TEnumType enumVal = (TEnumType)oInt;
                object oEnum = enumVal;
                names.Add((oEnum).ToString());
                i++;
            }
            return names.ToArray();
        }

        /// <summary>
        /// Gets a list of the enumerated values for the specified enumeration type.
        /// NOTE: The enum must not have explicit values set, so there are gaps in the value range, it must start at 0 and go up to max.
        /// </summary>
        /// <typeparam name="TEnumType"></typeparam>
        /// <returns></returns>
        public static TEnumType[] GetValues<TEnumType>()
        {
            Type type = typeof(TEnumType);
            if (!type.IsEnum)
                throw new ArgumentException("Type must be an enumeration.");

            List<TEnumType> values = new List<TEnumType>();
            int i = 0;
            while (System.Enum.IsDefined(type, i))
            {
                object o = i;
                TEnumType et = (TEnumType)o;
                values.Add(et);
                i++;
            }
            return values.ToArray();
        }

        /// <summary>
        /// Parse a string to an enumeration value given a defaul value if failed.
        /// </summary>
        /// <typeparam name="TEnumType">The enumeration type.</typeparam>
        /// <param name="value">A string containing the name or value to convert.</param>
        /// <param name="ignoreCase">If true, ignore case; otherwise, regard case.</param>
        /// <param name="defaultValue">The default value of the enumeration if the parsing fails.</param>
        /// <returns></returns>
        [DebuggerStepThrough]
        public static TEnumType Parse<TEnumType>(string value, bool ignoreCase, TEnumType defaultValue)
        {
            try
            {
                return (TEnumType)Enum.Parse(typeof(TEnumType), value, ignoreCase);
            }
            catch (ArgumentException)
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// Parse a string to a nullable enumeration value. If it's impossible to parse the string to this
        /// enumeration type, null is returned.
        /// </summary>
        /// <typeparam name="TEnumType">The enumeration type.</typeparam>
        /// <param name="value">A string containing the name or value to convert.</param>
        /// <param name="ignoreCase">If true, ignore case; otherwise, regard case.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentException">If TEnumType is not an enum.</exception>
        [DebuggerStepThrough]
        public static TEnumType? ParseDefaultNull<TEnumType>(string value, bool ignoreCase) where TEnumType : struct
        {
            if (!typeof(TEnumType).IsEnum)
                throw new ArgumentException("Type T Must be an Enum");

            if (string.IsNullOrEmpty(value))
                return null;

            try
            {
                return (TEnumType)Enum.Parse(typeof(TEnumType), value.Replace(typeof(TEnumType).Name + ".",""), ignoreCase);
            }
            catch (ArgumentException)
            {
                return null;
            }
        }

        
    }
}