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

namespace Apewer
{

    /// <summary>结果状态,Code 为零时表示正常,Code 0 与 NULL 相等。</summary>
    [Serializable]
    public class Result
    {

        private int _code;
        private string _message;
        private Exception _exception;

        /// <summary>代码。</summary>
        public int Code { get { return _code; } }

        /// <summary>消息。</summary>
        public string Message { get { return _message; } }

        /// <summary>异常。</summary>
        public Exception Exception { get { return _exception; } }

        /// <summary>创建实例:Code = 0,Message = NULL,Exception = NULL。</summary>
        public Result() { Construct(0, null, null); }

        /// <summary>创建实例:Message = NULL,Exception = NULL。</summary>
        public Result(int code) { Construct(code, null, null); }

        /// <summary>创建实例:Exception = NULL。</summary>
        public Result(int code, string message) { Construct(code, message, null); }

        /// <summary>创建实例:Code = -1,Exception = NULL。</summary>
        public Result(string message) { Construct(-1, message, null); }

        /// <summary>创建实例:Code = -2。</summary>
        public Result(Exception exception) { Construct(-2, null, exception); }

        private void Construct(int code, string message, Exception exception)
        {
            _code = code;
            if (exception == null)
            {
                _message = message;
            }
            else
            {
                _exception = exception;
                try { _message = _exception.Message; } catch { }
            }
        }

        /// <summary>判断相等。</summary>
        public override bool Equals(object obj)
        {
            return Equals(this, obj as Result);
        }

        /// <summary>获取哈希码。</summary>
        public override int GetHashCode()
        {
            return _code;
        }

        /// <summary>返回格式化的字符串,格式为:<para>Code 0 : Message Content</para></summary>
        public override string ToString()
        {
            var sb = new StringBuilder();
            sb.Append("Code ");
            sb.Append(_code.ToString());
            sb.Append(" : ");
            if (!string.IsNullOrEmpty(_message)) sb.Append(_message);
            var text = sb.ToString();
            return text;
        }

        /// <summary>判断相等。</summary>
        public static bool operator ==(Result left, Result right)
        {
            return Equals(left, right);
        }

        /// <summary>判断不等。</summary>
        public static bool operator !=(Result left, Result right)
        {
            return !Equals(left, right);
        }

        /// <summary>与 System.Int32 转换 Code 属性。</summary>
        public static implicit operator int(Result result)
        {
            return result == null ? 0 : result._code;
        }

        /// <summary>与 System.Int32 转换 Code 属性。</summary>
        public static implicit operator Result(int code)
        {
            return new Result(code);
        }

        private static bool Equals(Result left, Result right)
        {

            if (left as object == null)
            {
                if (right as object == null)
                {
                    return true;
                }
                else
                {
                    return right._code == 0;
                }
            }
            else
            {
                if (right as object == null)
                {
                    return left._code == 0;
                }
                else
                {
                    return left._code == right._code;
                }
            }
        }

        /// <summary>Code = 0,Message = NULL,Exception = NULL。</summary>
        public static Result Zero { get; } = new Result();

    }

    /// <summary>装箱返回结果,T 不适用于 System.String。</summary>
    [Serializable]
    public class Result<T> : IDisposable
    {

        private static readonly T Default = default(T);

        private T _entity = default(T);
        private Exception _exception = null;
        private int _code = 0;
        private string _message = Constant.EmptyString;

        /// <summary>对象。</summary>
        public T Entity { get { return _entity; } }

        /// <summary>异常。</summary>
        public Exception Exception { get { return _exception; } }

        /// <summary>代码。</summary>
        public int Code { get { return _code; } }

        /// <summary>消息,此属性永不为 Null 值,当存在 Exception 时将被 Exception.Message 强制覆盖。</summary>
        public string Message { get { return _message; } }

        /// <summary>含有实体对象。</summary>
        public bool HasEntity { get { return _entity != null; } }

        /// <summary>执行与释放或重置非托管资源关联的应用程序定义的任务。</summary>
        public void Dispose()
        {
            var entity = _entity as IDisposable;
            if (entity != null) entity.Dispose();
        }

        private void Construct(T entity, Exception exception, string message)
        {
            _entity = entity;
            _exception = exception;
            _message = message ?? Constant.EmptyString;
            if (_exception != null && TextVerifier.IsBlank(_message))
            {
                _message = _exception.Message;
            }
        }

        /// <summary>创建空结果,不含有实体、消息和异常。</summary>
        public Result() { }

        /// <summary>创建带有异常的结果。</summary>
        public Result(Exception exception) { Construct(Default, exception, null); }

        /// <summary>创建带有实体的结果。</summary>
        public Result(T entity) { Construct(entity, null, null); }

        /// <summary>创建带有实体和消息的结果。</summary>
        public Result(T argEntity, params string[] message) { Construct(argEntity, null, TextGenerator.Merge(message)); }

        /// <summary>创建带有错误消息的结果。</summary>
        public static Result<T> Error(params string[] message)
        {
            var instance = new Result<T>();
            var merged = TextGenerator.Merge(message);
            instance.Construct(Default, null, merged.IsEmpty() ? "存在无效消息。" : merged);
            return instance;
        }

        /// <summary>创建带有异常的结果,Exception 会覆盖 Message。</summary>
        public static Result<T> Error(Exception exception)
        {
            var instance = new Result<T>();
            instance.Construct(Default, exception, (exception == null ? "存在 NULL 异常。" : null));
            return instance;
        }

    }

}