using InABox.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;

namespace InABox.Core
{
    public interface IPollHandler
    {
        Type Type { get; }

        /// <summary>
        /// Polls for notifications, called on client connection.
        /// </summary>
        /// <returns>New notifications</returns>
        IEnumerable<BaseObject> Poll(Guid session);
    }
    public class PollHandler<TNotification> : IPollHandler
        where TNotification : BaseObject
    {
        public delegate IEnumerable<TNotification> PollEvent(Guid session);

        public event PollEvent? OnPoll;

        public Type Type => typeof(TNotification);

        public PollHandler() { }

        public PollHandler(PollEvent poll)
        {
            OnPoll += poll;
        }

        public IEnumerable<BaseObject> Poll(Guid session) => OnPoll?.Invoke(session) ?? Array.Empty<TNotification>();
    }


    public abstract class Notifier
    {
        protected abstract void NotifyAll<TNotification>(TNotification notification) where TNotification : BaseObject;
        protected abstract void NotifySession<TNotification>(Guid session, TNotification notification) where TNotification : BaseObject;
        protected abstract void NotifySession(Guid session, Type TNotification, BaseObject notification);
        protected abstract IEnumerable<Guid> GetUserSessions(Guid user);
        protected abstract IEnumerable<Guid> GetSessions(Platform platform);

        public void Push<TNotification>(TNotification notification)
            where TNotification : BaseObject
        {
            NotifyAll(notification);
        }

        public void Push(Guid session, Type TNotification, BaseObject notification)
        {
            NotifySession(session, TNotification, notification);
        }

        public void Push<TNotification>(Guid session, TNotification notification)
            where TNotification : BaseObject
        {
            NotifySession(session, notification);
        }
        public void PushUser<TNotification>(Guid user, TNotification notification)
            where TNotification : BaseObject
        {
            foreach (var session in GetUserSessions(user))
            {
                NotifySession(session, notification);
            }
        }
        public void Push<TNotification>(Platform platform, TNotification notification)
            where TNotification : BaseObject
        {
            foreach (var session in GetSessions(platform))
            {
                NotifySession(session, notification);
            }
        }

    }
}