using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace HelloWorld
{
    public class Receiver : IDisposable
    {
        private readonly ConnectionFactory _connectionFactory;
        private readonly IConnection _connection;
        private readonly IModel _channel;

        private readonly string _queueName;

        public Receiver(string brockerHost, string brockerUsername, string brockerPassword, string queueName)
        {
            _queueName = queueName;
            _connectionFactory = new ConnectionFactory() { HostName = brockerHost, UserName = brockerUsername, Password = brockerPassword };
            _connection = _connectionFactory.CreateConnection();
            _channel = _connection.CreateModel();

            _channel.QueueDeclare(queue: _queueName,
                                    durable: true,
                                    exclusive: false,
                                    autoDelete: false,
                                    arguments: null);

            _channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
        }

        public bool AddMessageHandler(Action<string> handler)
        {
            try
            {
                var consumer = new EventingBasicConsumer(_channel);
                consumer.Received += (model, ea) =>
                {
                    var messageBody = ea.Body.ToArray();
                    var messageText = Encoding.UTF8.GetString(messageBody);

                    handler(messageText);

                    _channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                };
                _channel.BasicConsume(queue: _queueName,
                                     autoAck: false,
                                     consumer: consumer);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return false;
        }

        ~Receiver() => Dispose();

        public void Dispose()
        {
            _connection.Dispose();
            _channel.Dispose();
        }
    }
}