﻿/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace DotPulsar.Internal
{
    using DotPulsar.Abstractions;
    using DotPulsar.Exceptions;

    public sealed class ProducerBuilder<TMessage> : IProducerBuilder<TMessage>
    {
        private readonly IPulsarClient _pulsarClient;
        private readonly ISchema<TMessage> _schema;
        private string? _producerName;
        private CompressionType _compressionType;
        private ulong _initialSequenceId;
        private string? _topic;
        private IHandleStateChanged<ProducerStateChanged>? _stateChangedHandler;
        private IMessageRouter? _messageRouter;

        public ProducerBuilder(IPulsarClient pulsarClient, ISchema<TMessage> schema)
        {
            _pulsarClient = pulsarClient;
            _schema = schema;
            _compressionType = ProducerOptions<TMessage>.DefaultCompressionType;
            _initialSequenceId = ProducerOptions<TMessage>.DefaultInitialSequenceId;
        }

        public IProducerBuilder<TMessage> CompressionType(CompressionType compressionType)
        {
            _compressionType = compressionType;
            return this;
        }

        public IProducerBuilder<TMessage> InitialSequenceId(ulong initialSequenceId)
        {
            _initialSequenceId = initialSequenceId;
            return this;
        }

        public IProducerBuilder<TMessage> ProducerName(string name)
        {
            _producerName = name;
            return this;
        }

        public IProducerBuilder<TMessage> StateChangedHandler(IHandleStateChanged<ProducerStateChanged> handler)
        {
            _stateChangedHandler = handler;
            return this;
        }

        public IProducerBuilder<TMessage> Topic(string topic)
        {
            _topic = topic;
            return this;
        }

        public IProducerBuilder<TMessage> MessageRouter(IMessageRouter messageRouter)
        {
            _messageRouter = messageRouter;
            return this;
        }

        public IProducer<TMessage> Create()
        {
            if (string.IsNullOrEmpty(_topic))
                throw new ConfigurationException("ProducerOptions.Topic may not be null or empty");

            var options = new ProducerOptions<TMessage>(_topic!, _schema)
            {
                CompressionType = _compressionType,
                InitialSequenceId = _initialSequenceId,
                ProducerName = _producerName,
                StateChangedHandler = _stateChangedHandler
            };

            if (_messageRouter is not null)
                options.MessageRouter = _messageRouter;

            return _pulsarClient.CreateProducer(options);
        }
    }
}
