using StackExchange.Redis;
using System;
using VCommon.Logging;
using VCommon.Services;

namespace VCommon.PubSub
{
    public abstract class Subscriber : PubSubBase, IService
    {
        protected Subscriber(string server, string channelName) : base(server, channelName)
        {
        }

        private void OnMessageArrival(RedisChannel channel, RedisValue content)
        {
            Logger.Trace($"{nameof(PubSub)}:{nameof(Subscriber)} Event", new { ChannelName, Content = (string)content });
            try
            {
                HandleEvent(content);
            }
            catch (Exception exception)
            {
                Logger.Error($"{nameof(PubSub)}:{nameof(Subscriber)} Error on handling event", new { ChannelName, exception });
            }
        }

        public override void Dispose()
        {
            Stop();
            base.Dispose();
        }

        protected abstract void HandleEvent(string message);

        public void Start()
        {
            Logger.Trace($"{nameof(PubSub)}:{nameof(Subscriber)} Start", ChannelName);
            Conn.GetSubscriber().Subscribe(ChannelName, OnMessageArrival);
        }

        public void Stop()
        {
            Logger.Trace($"{nameof(PubSub)}:{nameof(Subscriber)} Stop", ChannelName);
            Conn.GetSubscriber().Unsubscribe(ChannelName, OnMessageArrival);
        }
    }
}
