using System;

using Prism.Events;

// https://prismlibrary.com/docs/event-aggregator.html

namespace TopNugetPackages
{
    /// <summary>
    /// EventService provider that instantiates the event hub for all classes
    /// The one and only event hub service provider for all classes that usages it
    /// Replaces the mediator class functionalities in [MediatR]
    /// </summary>
    internal sealed class EventService
    {
        private EventService() { }

        private static readonly EventService _instance = new EventService();

        internal static EventService Instance { get { return _instance; } }

        private IEventAggregator _eventAggregator;
        internal IEventAggregator EventAggregator
        {
            get
            {
                if (_eventAggregator == null)
                    _eventAggregator = new EventAggregator();

                return _eventAggregator;
            }
        }
    }

    // Define each event
    // Define as many event as needed, with different event or parameters
    public class SamplePubSubTest : PubSubEvent<string> { }

    /// ////////////////////////////////////////////////////////////////////////////////////////

    // Subscriber class
    internal class EventSubscriber
    {
        private IEventAggregator ea = EventService.Instance.EventAggregator;

        public void SubscribeEvent()
        {
            ea.GetEvent<SamplePubSubTest>().Subscribe(OnEventReceived);
        }

        private void OnEventReceived(string str)
        {
            Console.WriteLine(str);
        }
    }

    // Publisher class
    internal class EventPublisher
    {
        private IEventAggregator ea = EventService.Instance.EventAggregator;

        public void PublishEvent()
        {
            ea.GetEvent<SamplePubSubTest>().Publish($"Hello World: The time is {DateTime.Now}");
        }
    }

    /// <summary>
    // Main driver class
    // The purpose of the event hub is to drive a mediator pattern into two different classes.
    // The classes are suppose to be loosely coupled and have no dependency on each other.
    // And in such case, we can send messages and/or event to one another without having the classes
    // to know one or the other exist. The is usefull for passing data around between classes.
    /// </summary>
    public class MainEventHubDriver
    {
        public void RunPubSubEvent()
        {
            var sub = new EventSubscriber();
            sub.SubscribeEvent();

            var pub = new EventPublisher();
            pub.PublishEvent();
        }
    }
}