using System;
using System.Collections.Generic;

namespace Microscopic_Traffic_Simulator.ViewModels.Messages
{
    /// <summary>
    /// Class representing message with payload.
    /// </summary>
    abstract class ParameterizedMessage<TPayload> : MessageBase
    {
        /// <summary>
        /// List of subscribers of message.
        /// </summary>
        private HashSet<Action<TPayload>> subscribers = new HashSet<Action<TPayload>>();

        /// <summary>
        /// Subscribe to this message.
        /// </summary>
        /// <param name="subscriber">Action with payload of type TPayload executed after 
        /// receiving this message.</param>        
        internal void Subscribe(Action<TPayload> subscriber)
        {
            subscribers.Add(subscriber);
        }

        /// <summary>
        /// Unsubscribe from this message.
        /// </summary>
        /// <param name="subscriber">Action with payload of type TPayload executed after 
        /// receiving this message.</param>
        internal void Unsubcsribe(Action<TPayload> subscriber)
        {
            subscribers.Remove(subscriber);
        }

        /// <summary>
        /// Publish message with payload to all subscribers.
        /// </summary>
        internal void Publish(TPayload payload)
        {
            foreach (Action<TPayload> subscriber in subscribers)
            {
                subscriber(payload);
            }
        }
    }

    /// <summary>
    /// Class representing message with payload.
    /// </summary>
    abstract class ParameterizedMessage<TPayload, TPayload2> : MessageBase
    {
        /// <summary>
        /// List of subscribers of message.
        /// </summary>
        private HashSet<Action<TPayload, TPayload2>> subscribers = new HashSet<Action<TPayload, TPayload2>>();

        /// <summary>
        /// Subscribe to this message.
        /// </summary>
        /// <param name="subscriber">Action with payload of type TPayload executed after 
        /// receiving this message.</param>        
        internal void Subscribe(Action<TPayload, TPayload2> subscriber)
        {
            subscribers.Add(subscriber);
        }

        /// <summary>
        /// Unsubscribe from this message.
        /// </summary>
        /// <param name="subscriber">Action with payload of type TPayload executed after 
        /// receiving this message.</param>
        internal void Unsubcsribe(Action<TPayload, TPayload2> subscriber)
        {
            subscribers.Remove(subscriber);
        }

        /// <summary>
        /// Publish message with payload to all subscribers.
        /// </summary>
        internal void Publish(TPayload payload, TPayload2 payload2)
        {
            foreach (Action<TPayload, TPayload2> subscriber in subscribers)
            {
                subscriber(payload, payload2);
            }
        }
    }
}
