/********************************
 *
 * 作者:吴隆健
 * 创建时间: 2019/6/24 15:27:55
 * 
 ********************************/

#if RABBITMQ

using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;

namespace MrWu.RabbitMQ {

    /// <summary>
    /// 消息委托
    /// </summary>
    /// <param name="msg"></param>
    public delegate void MessageHandle(Message msg);

    /// <summary>
    /// 消息
    /// </summary>
    public class Message {

        /// <summary>
        /// 日志用的查 慢的问题
        /// </summary>
        public DateTime logTime;

        private static Exception ex {
            get {
                return new Exception("引用已释放的对象!");
            }
        }

        /// <summary>
        /// 是否已经释放
        /// </summary>
        internal bool isFree = false;

        private string m_exchange;
        /// <summary>
        /// 路由
        /// </summary>
        public string exchange {
            get {
                if (isFree)
                    throw ex;
                return m_exchange;
            }
            set {
                if (isFree)
                    throw ex;
                m_exchange = value;
            }
        }

        private string m_routingkey;
        /// <summary>
        /// 路由键
        /// </summary>
        public string routingkey {
            get {
                if (isFree)
                    throw ex;
                return m_routingkey;
            }
            set {
                if (isFree)
                    throw ex;
                m_routingkey = value;
            }
        }

        private bool m_durable;

        public bool durable
        {
            get
            {
                if (isFree)
                    throw ex;
                return m_durable;
            }
            set
            {
                if (isFree)
                    throw ex;

                m_durable = value;
            }
        }

        private bool m_mandatory;
        /// <summary>
        /// 无法路由是否触发return事件
        /// </summary>
        public bool mandatory {
            get {
                if (isFree)
                    throw ex;
                return m_mandatory;
            }
            set {
                if (isFree)
                    throw ex;
                m_mandatory = value;
            }
        }

        /// <summary>
        /// 消息内容
        /// </summary>
        public byte[] body {
            get {
                if (isFree)
                    throw ex;
                //Debug.Debug.Log("消息内容:" + bodystr);
                return Encoding.UTF8.GetBytes(bodystr);
            }
            set {
                if (isFree)
                    throw ex;
                bodystr = Encoding.UTF8.GetString(value);
            }
        }

        private string m_bodystr;
        /// <summary>
        /// 消息内容
        /// </summary>
        public string bodystr {
            get {
                if (isFree)
                    throw ex;
                return m_bodystr;
            }
            set {
                if (isFree)
                    throw ex;
                m_bodystr = value;
            }
        }

        private IBasicProperties m_propertis;

        /// <summary>
        /// 消息的属性
        /// </summary>
        public IBasicProperties propertis {
            get {
                if (isFree)
                    throw ex;
                return m_propertis;
            }
            set {
                if (isFree)
                    throw ex;
                m_propertis = value;
            }
        }

        private ulong m_deliveryTag;
        /// <summary>
        /// 投递的或接收的消息标志
        /// </summary>
        public ulong deliveryTag {
            get {
                if (isFree)
                    throw ex;
                return m_deliveryTag;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_deliveryTag = value;
            }
        }

        private string m_id;

        /// <summary>
        /// 消息的唯一标识
        /// </summary>
        public string id {
            get {
                if (isFree)
                    throw ex;
                return m_id;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_id = value;
            }
        }

        private bool m_success;
        /// <summary>
        /// 是否发送成功
        /// </summary>
        public bool success {
            get {
                if (isFree)
                    throw ex;
                return m_success;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_success = value;
            }
        }

        private bool m_isAutoFree;

        /// <summary>
        /// 是否发送完毕自动释放
        /// </summary>
        public bool isAutoFree {
            get {
                if (isFree)
                    throw ex;
                return m_isAutoFree;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_isAutoFree = value;
            }
        }

        /// <summary>
        /// 发送失败事件
        /// </summary>
        public MessageHandle SendResult = null;



        private IDictionary<string, object> m_useradata;
        /// <summary>
        /// 暂存数据,客户端发送失败可能用的上
        /// </summary>
        public IDictionary<string, object> userData {

            get {
                if (isFree)
                    throw ex;
                return m_useradata;
            }
            set {
                if (isFree)
                    throw ex;
                m_useradata = value;
            }
        }

        private IModel m_channel;

        /// <summary>
        /// 处理该消息的信道
        /// </summary>
        internal IModel channel {
            get {
                if (isFree)
                    throw ex;
                return m_channel;
            }
            set {
                if (isFree)
                    throw ex;
                m_channel = value;
            }
        }

        private bool m_noAck;

        /// <summary>
        /// 是否需要确认
        /// </summary>
        public bool noAck {
            get {
                if (isFree)
                    throw ex;
                return m_noAck;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_noAck = value;
            }
        }

        private bool m_redelivered;

        /// <summary>
        /// 是否被重复接收过
        /// </summary>
        public bool redelivered {
            get {
                if (isFree)
                    throw ex;
                return m_redelivered;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_redelivered = value;
            }
        }

        private uint m_messageCount;
        /// <summary>
        /// 剩余消息的数量
        /// </summary>
        public uint messageCount {
            get {
                if (isFree)
                    throw ex;
                return m_messageCount;
            }
            internal set {
                if (isFree)
                    throw ex;
                m_messageCount = value;
            }
        }

        /// <summary>
        /// 确认
        /// </summary>
        /// <returns></returns>
        public bool Ack(bool multiple = false) {
            if (isFree)
                throw ex;
            if (channel == null)
                return false;
            lock (channel) {
                try {
                    channel.BasicAck(deliveryTag, multiple);
                } catch (Exception e) {
                    Debug.Debug.Error("确认消息出错:" + e.ToString());
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 拒绝确认
        /// </summary>
        /// <returns></returns>
        public bool NAck(bool multiple = false, bool requeue = false) {
            if (isFree)
                throw ex;
            if (channel == null)
                return false;
            lock (channel) {
                try {
                    channel.BasicNack(deliveryTag, multiple, requeue);
                } catch (Exception e) {
                    Debug.Debug.Error("拒绝消息出错:" + e.ToString());
                    return false;
                }
            }
            return true;
        }

        private long m_createTime;
        /// <summary>
        /// 发送的逻辑时间
        /// </summary>
        internal long createTime {
            get {
                if (isFree)
                    throw ex;
                return m_createTime;
            }
            set {
                if (isFree)
                    throw ex;
                m_createTime = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        internal Message() {
        }

        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="id"></param>
        //internal Message(string id) {
        //    this.id = id;
        //    createTime = Debug.Debug.timevalue;
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString() {
            if (isFree)
                throw ex;
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("exchange:" + exchange);
            sb.AppendLine("routingkey:" + routingkey);
            sb.AppendLine("mandatory:" + mandatory);
            sb.AppendLine("deliveryTag:" + deliveryTag);
            sb.AppendLine("success:" + success);
            sb.AppendLine("body:" + bodystr);

            return sb.ToString();
        }

        /// <summary>
        /// 克隆一个
        /// </summary>
        /// <returns></returns>
        public Message Clone() {
            Message result = new Message();
            result.isFree = this.isFree;
            result.exchange = this.exchange;
            result.routingkey = this.routingkey;
            result.mandatory = this.mandatory;
            result.bodystr = this.bodystr;
            result.propertis = this.propertis;
            result.deliveryTag = this.deliveryTag;
            result.id = this.id;
            result.success = this.success;
            result.isAutoFree = this.isAutoFree;
            result.userData = this.userData;
            result.SendResult = this.SendResult;
            result.channel = this.channel;
            result.noAck = this.noAck;
            result.redelivered = this.redelivered;
            result.messageCount = this.messageCount;
            result.createTime = this.createTime;
            return result;
        }

        /// <summary>
        /// 清楚事件
        /// </summary>
        public void Clear() {
            success = false;
            noAck = false;
            isAutoFree = false;
            SendResult = null;
            exchange = null;
            routingkey = null;
            bodystr = null;
            propertis = null;
            userData = null;
            channel = null;
        }

        ///// <summary>
        ///// Dispose
        ///// </summary>
        //public void Dispose() {
        //    this.id = null;
        //    this.exchange = null;
        //    this.routingkey = null;
        //    this.bodystr = null;
        //    this.propertis?.Headers?.Clear();
        //    this.propertis = null;

        //    this.userData?.Clear();
        //    this.userData = null;
        //    this.channel = null;

        //    if(this.SendResult != null) {
        //        var deles = this.SendResult.GetInvocationList();
        //        foreach(MessageHandle dele in deles) {
        //            this.SendResult -= dele;
        //        }
        //    }

        //    GC.SuppressFinalize(this);
        //}
    }
}
#endif