using System;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using MQTTnet.Client;
using System.Security.Authentication;
using MQTTnet;
using Microsoft.Extensions.Logging;

#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* 版权所有 (c) 2024 WenJY 保留所有权利。
* CLR版本:4.0.30319.42000
* 机器名称:LAPTOP-E0N2L34V
* 命名空间:SlnMesnac.Mqtt
* 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
*
* 创建者:WenJY
* 电子邮箱:wenjy@mesnac.com
* 创建时间:2024-03-27 21:58:35
* 版本:V1.0.0
* 描述:
*
*--------------------------------------------------------------------
* 修改人:
* 时间:
* 修改说明:
*
* 版本:V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
namespace SlnMesnac.Mqtt
{
    /// <summary>
    /// MQTT客户端
    /// </summary>
    public class MqttClient
    {
        private ILogger<MqttClient> _logger;

        private IMqttClient _client;

        public MqttClient(ILogger<MqttClient> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 链接服务器
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="clientId"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public async void Connect(string ip, int port, string clientId, string username, string password)
        {
            try
            {
                MqttClientOptions options = new MqttClientOptionsBuilder()
                .WithTcpServer(ip, port)
                .WithClientId(clientId)
                .WithCredentials(username, password)
                .WithTls(o =>   //开启ssl
                {
                    o.CertificateValidationHandler = _ => true;

                    o.SslProtocol = SslProtocols.Tls12;
                })
                .Build();
                _client = new MqttFactory().CreateMqttClient();

                _client.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceived;

                MqttClientConnectResult result = await _client.ConnectAsync(options);

                if (result != null)
                {
                    if (result.ResultCode == MQTTnet.Client.MqttClientConnectResultCode.Success)
                    {
                        _logger.LogInformation($"连接服务器成功{ip}:{port}");
                    }
                    else
                    {
                        _logger.LogInformation($"连接服务器失败");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("连接服务器异常",ex);
            }
        }

        /// <summary>
        /// 断开链接
        /// </summary>
        public void DisConnect()
        {
            _client.DisconnectAsync();
            _logger.LogInformation($"断开连接");
        }

        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topic"></param>
        public async void SubscriptionAsync(string topic)
        {
            try
            {
                var mqttFactory = new MqttFactory();
                var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
                    .WithTopicFilter(
                        f =>
                        {
                            f.WithTopic(topic);
                        })
                    .Build();

                MqttClientSubscribeResult result = await _client.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

                _logger.LogInformation($"订阅主题:{topic}");
            }
            catch (Exception ex)
            {
                _logger.LogError("订阅主题异常",ex);
            }
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="topic"></param>
        public void Unsubscribe(string topic)
        {
            _client.UnsubscribeAsync(topic);
            _logger.LogInformation($"取消订阅,主题:{topic}");
        }

        /// <summary>
        /// 推送消息
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        public void Publish(string topic, string message)
        {
            try
            {
                var msg = new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(message)
                .Build();
                _client.PublishAsync(msg, CancellationToken.None);
                _logger.LogInformation($"向服务端推送成功,主题:{topic};内容:{message}");
            }
            catch (Exception ex)
            {
                _logger.LogError("向服务端推送消息异常",ex);
            }
        }

        private async Task MqttClient_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs eventArgs)
        {
            var info = $"接收到主题:{eventArgs.ApplicationMessage.Topic}的消息,内容:{Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)}";
            _logger.LogInformation(info);
        }

    }
}