using HslCommunication;
using HslCommunication.Enthernet.Redis;
using HslCommunication.MQTT;
using MWS.Data.InterFace;
using MWS.Data.Manager;
using MWS.Domain.Dto;
using MWS.Library;
using MWS.Library.Common;
using MWS.Model;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Documents;

namespace MWS.Domain.Tasks
{
    public class TeamRotate
    {
        private readonly Thread thread;
        private RedisClient _redisClient;
        private MqttClient _mqttClient;
        private readonly ITeam teamManager;

        public TeamRotate()
        {
            #region Redis
            var redisAddress = ConfigurationManager.AppSettings["RedisAddress"];
            var redisPort = ConfigurationManager.AppSettings["RedisPort"];
            var redisTagDb = ConfigurationManager.AppSettings["RedisTagDb"];
            _redisClient = new RedisClient(redisAddress, int.Parse(redisPort), null);
            var operateResult = _redisClient.ConnectServer();
            _redisClient.SelectDB(int.Parse(redisTagDb));
            if (!operateResult.IsSuccess)
            {
                LogHelper.WriteLog("Redis服务连接失败！错误：" + operateResult.Message);
            }
            #endregion
            #region MQTT
            var mqttPort = ConfigurationManager.AppSettings["MqttPort"];
            _mqttClient = new MqttClient(new MqttConnectionOptions
            {
                ClientId = Guid.NewGuid().ToString("N").ToUpper(),
                IpAddress = "127.0.0.1",
                Port = mqttPort.ToInt(),
            });
            operateResult = _mqttClient.ConnectServer();
            if (!operateResult.IsSuccess)
            {
                LogHelper.WriteLog("MQTT服务连接失败！错误：" + operateResult.Message);
            }
            else
            {
                _mqttClient.OnNetworkError += MqttClient_OnNetworkError;
            }
            #endregion
            teamManager = new TeamManager();
            thread = new Thread(new ThreadStart(ThreadCapture))
            {
                IsBackground = true
            };
            thread.Start();
        }

        private void ThreadCapture()
        {
            var teams = teamManager.GetAll<Team>().ToList();
            OperateResult<string> readResult;
            OperateResult<int> exitResult;
            DateTime nowTime;
            DateTime endTime;
            JObject teamObject;
            NextTeamDto nextTeam= GetNextTeam(teams, DateTime.Now);
            //endTime = nextTeam.EndTime;
            //if (endTime <= DateTime.Now)
            //{
            //    nextTeam = GetNextTeam(teams, DateTime.Now);
            WriteAndPublish(nextTeam);
            //}
            while (true)
            {
                nowTime = DateTime.Now;
                exitResult = _redisClient.ExistsKey("CurrentTeam");
                if (exitResult.IsSuccess)
                {
                    if (exitResult.Content == 1)
                    {
                        readResult = _redisClient.ReadKey("CurrentTeam");
                        if (readResult.IsSuccess)
                        {
                            teamObject = JObject.Parse(readResult.Content);
                            endTime = teamObject.GetValue("EndTime").ToObject<DateTime>();
                            if (endTime <= nowTime)
                            {
                                nextTeam = GetNextTeam(teams, nowTime);
                                WriteAndPublish(nextTeam);
                            }
                        }
                        else
                        {
                            LogHelper.WriteLog("读取“CurrentTeam”是时失败，错误：" + exitResult.Message);
                        }
                    }
                    else
                    {
                        nextTeam = GetNextTeam(teams, nowTime);
                        WriteAndPublish(nextTeam);
                    }
                }
                else
                {
                    LogHelper.WriteLog("读取“CurrentTeam”是否存在时失败，错误：" + exitResult.Message);
                }
                Thread.Sleep(1000 * 60);
            }
        }

        private NextTeamDto GetNextTeam(List<Team> teams, DateTime nowTime)
        {
            var query = from team in teams
                        let sp1 = TimeSpan.Parse(team.StartTime)
                        let sp2 = TimeSpan.Parse(team.EndTime)
                        let start = sp1 > sp2 ? (nowTime.TimeOfDay > sp1 ? nowTime.Date + sp1 : nowTime.AddDays(-1).Date + sp1) : nowTime.Date + sp1
                        let end = sp1 > sp2 ? (nowTime.TimeOfDay > sp1 ? nowTime.AddDays(1).Date + sp2 : nowTime.Date + sp2) : nowTime.Date + sp2
                        where nowTime >= start && nowTime < end
                        select new NextTeamDto { Id = team.Id, Name = team.Name, StartTime = start, EndTime = end };
            return query.FirstOrDefault();
        }

        private void WriteAndPublish(NextTeamDto nextTeam)
        {
            if (nextTeam != null)
            {
                var teamObject = new JObject {
                                   new JProperty("Id", nextTeam.Id),
                                   new JProperty("Name", nextTeam.Name),
                                   new JProperty("StartTime", nextTeam.StartTime),
                                   new JProperty("EndTime", nextTeam.EndTime),
                                 };
                var result = _redisClient.WriteKey("CurrentTeam", teamObject.ToString());
                if (!result.IsSuccess)
                {
                    LogHelper.WriteLog("向Redis写入CurrentTeam失败:" + result.Message);
                }
            }
            else
            {
                var deleteResult = _redisClient.DeleteKey("CurrentTeam");
                if (!deleteResult.IsSuccess)
                {
                    LogHelper.WriteLog("删除“CurrentTeam”时失败，错误：" + deleteResult.Message);
                }
            }
            var publishResult = _mqttClient.PublishMessage(new MqttApplicationMessage
            {
                Topic = "TeamChange",
                Payload = Encoding.UTF8.GetBytes(new JObject(new JProperty("Id", nextTeam?.Id ?? 0), new JProperty("Name", nextTeam?.Name ?? "空闲")).ToString())
            });
            if (!publishResult.IsSuccess)
            {
                LogHelper.WriteLog("发布主题“TeamChange”时失败，错误：" + publishResult.Message);
            }
        }

        private void MqttClient_OnNetworkError(object sender, EventArgs e)
        {
            // 当网络异常的时候触发，可以在此处重连服务器
            if (sender is MqttClient client)
            {
                // 开始重连服务器，直到连接成功为止
                Console.WriteLine("网络异常，准备5秒后重新连接。");
                while (true)
                {
                    // 每隔5秒重连
                    Thread.Sleep(5000);
                    Console.WriteLine("准备重新连接服务器...");
                    OperateResult connect = client.ConnectServer();
                    if (connect.IsSuccess)
                    {
                        // 连接成功后，可以在下方break之前进行订阅，或是数据初始化操作
                        Console.WriteLine("连接服务器成功！");
                        break;
                    }
                    Console.WriteLine("连接失败，准备5秒后重新连接。");
                }
            }
        }

    }
}