using System;

namespace Apewer
{

    /// <summary>装箱类。</summary>
    public sealed class Class<T> : IDisposable // : IComparable, IComparable<T>, IComparable<Class<T>>
    {

        /// <summary>值。</summary>
        public T Value { get; set; }

        /// <summary>创建装箱实例,值为默认值。</summary>
        public Class() { }

        /// <summary>创建装箱实例,值为指定值。</summary>
        public Class(T value) => Value = value;

        #region IDisposable

        /// <summary>如果 <see cref="Value" /> 实现了 <see cref="IDisposable" />,则释放 <see cref="Value" /> 占用的系统资源。</summary>
        public void Dispose() => RuntimeUtility.Dispose(Value);

        #endregion

        #region Override

        /// <summary></summary>
        public override int GetHashCode()
        {
            if (Value != null) return Value.GetHashCode();
            return base.GetHashCode();
        }

        /// <summary></summary>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj)) return true;

            var right = obj as Class<T>;
            if (Value.IsNull())
            {
                if (right == null) return true;
                if (right.Value.IsNull()) return true;
                return false;
            }
            else
            {
                if (right == null) return false;
                if (right.Value.IsNull()) return false;
                if (ReferenceEquals(Value, right.Value)) return true;
                return Value.Equals(right.Value);
            }
        }

        /// <summary></summary>
        public override string ToString()
        {
            if (Value == null) return null;
            return Value.ToString();
        }

        #endregion

#if ClassCompare

        #region Compare

        /// <summary></summary>
        /// <exception cref="NotSupportedException"></exception>
        public int CompareTo(object obj)
        {
            if (typeof(IComparable).IsAssignableFrom(typeof(T)))
            {
                var comparable = Value as IComparable;
                if (comparable.IsNull())
                {
                    if (obj is Class<T> bro)
                    {
                        if (bro == null) return 0;
                        if (bro.Value.IsNull()) return 0;
                        return -1;
                    }

                    if (obj.IsNull()) return 0;
                    return -1;
                }
                else
                {
                    if (obj != null && obj is Class<T> bro) return comparable.CompareTo(bro.Value);
                    return comparable.CompareTo(obj);
                }
            }

            throw new NotImplementedException($"类型 {typeof(T).Name} 没有实现 {nameof(IComparable)} 接口。");
        }

        /// <summary></summary>
        /// <exception cref="MissingMemberException"></exception>
        /// <exception cref="NotSupportedException"></exception>
        public int CompareTo(T other)
        {
            if (Value == null) throw new MissingMemberException(typeof(T).FullName, nameof(Value));
            if (!(Value is IComparable)) throw new NotSupportedException();
            return ((IComparable<T>)Value).CompareTo(other);
        }

        /// <summary></summary>
        /// <exception cref="MissingMemberException"></exception>
        /// <exception cref="NotSupportedException"></exception>
        public int CompareTo(Class<T> other)
        {
            if (Value == null) throw new MissingMemberException(typeof(T).FullName, nameof(Value));

            if (Value is IComparable) return ((IComparable)Value).CompareTo(other.Value);
            if (Value is IComparable<T>) return ((IComparable<T>)Value).CompareTo(other.Value);

            throw new NotSupportedException();
        }

        #endregion

#endif

        #region 运算符。

        /// <summary>从 <see cref="Class{T}"/> 到 Boolean 的隐式转换,判断 <see cref="Class{T}"/> 包含值。</summary>
        /// <remarks>当 T 是 Boolean 时,获取 Value。<br />当 T 是 String 时,判断 Value 不为 NULL 且不为空。</remarks>
        public static implicit operator bool(Class<T> instance)
        {
            if (instance == null) return false;

            // var boolean = instance as Class<bool>;
            // if (boolean != null) return boolean.Value;

            // var text = instance as Class<string>;
            // if (text != null) return !string.IsNullOrEmpty(text.Value);

            return true;
        }

        // /// <summary>从 <see cref="Class{T}"/> 到 T 的隐式转换。</summary>
        // public static implicit operator T(Class<T> instance)
        // {
        //     if (instance == null) return default(T);
        //     if (typeof(T).Equals(typeof(bool))) return instance.Value;
        //     return instance.Value;
        // }

        // /// <summary>从 T 到 <see cref="Class{T}"/> 的隐式转换。</summary>
        // public static implicit operator Class<T>(T value) => new Class<T>(value);

        #endregion

    }

}