using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Performance.Infrastructure;
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;

namespace Performance.Services.Queues
{

    public interface IHubNotificationQueue
    {
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="message"></param>
        void Send(Notification message);
    }
    public class HubNotificationQueue : IHubNotificationQueue
    {
        private readonly ILogger<HubNotificationQueue> _logger;
        private IHubContext<AllotLogHub> _hubContext;
        private BlockingCollection<Notification> _queue;
        public HubNotificationQueue(
            ILogger<HubNotificationQueue> logger,
            IHubContext<AllotLogHub> hubContext)
        {
            _logger = logger;
            _hubContext = hubContext;
            _queue = new BlockingCollection<Notification>();
            Task.Factory.StartNew(() => Consumer());
        }

        public void Send(Notification message)
        {
            _queue.TryAdd(message);
        }

        private void Consumer()
        {
            foreach (var item in _queue.GetConsumingEnumerable())
            {
                _logger.LogInformation(
                    "ConectionId GroupName：{ConectionId}；消息推送：{Method}；内容：{Body}",
                    item.UserId.ToString(),
                    item.Method,
                    JsonHelper.Serialize(item.Body));
                _hubContext.Clients.Group(item.UserId.ToString()).SendAsync(item.Method, item.Body);
            }
        }
    }
    public enum NotificationLevel
    {
        [Description("通知")] INF = 1,
        [Description("警告")] WAR = 2,
        [Description("错误")] ERR = 3,
    }
    public class Notification
    {
        public Notification(int userId, string method, PushContent body)
        {
            UserId = userId;
            Method = method;
            Body = body;
        }

        public int UserId { get; set; }
        public string Method { get; set; }
        public PushContent Body { get; set; }

        public abstract class PushContent
        {
            protected PushContent(string subject, NotificationLevel level)
            {
                Subject = subject;
                LogLevel = (int)level;
            }

            public abstract string Type { get; }
            public int LogLevel { get; }
            public string Time { get => DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); }
            public string Subject { get; set; }
        }
    }

    public class EventContent : Notification.PushContent
    {
        public EventContent(object eventId, string subject, string content, NotificationLevel level = NotificationLevel.INF)
            : base(subject, level)
        {
            EventId = eventId;
            Content = content;
        }

        public object EventId { get; set; }
        public string Content { get; set; }

        public override string Type => "Event";
    }
    public class TextContent : Notification.PushContent
    {
        public TextContent(string content, NotificationLevel level = NotificationLevel.INF)
            : base(content, level)
        {
        }

        public override string Type => "Text";
    }
    public class UrlContent : Notification.PushContent
    {
        public UrlContent(string subject, string url, NotificationLevel level = NotificationLevel.INF)
            : base(subject, level)
        {
            Content = url;
        }
        public string Content { get; set; }
        public override string Type => "Url";
    }
    public class CustomDownloadContent : Notification.PushContent
    {
        public CustomDownloadContent(string subject, object @object, NotificationLevel level = NotificationLevel.INF)
            : base(subject, level)
        {
            Arguments = @object;
        }

        public override string Type => "CustomDownload";
        public object Arguments { get; set; }
    }
}
