using InABox.API;
using InABox.Core;

namespace InABox.IPC
{
    public class IPCNotifier : Notifier
    {
        IPCNotifyState NotifyState { get; set; }

        public IPCNotifier(IPCNotifyState notifyState)
        {
            NotifyState = notifyState;
            NotifyState.OnPoll += NotifyState_OnPoll;
        }

        private void NotifyState_OnPoll(IPCNotifyState.Session session)
        {
            Notify.Poll(session.SessionID);
        }

        protected override IEnumerable<Guid> GetSessions(Platform platform)
        {
            return NotifyState.SessionMap.Where(x => x.Value.Platform == platform).Select(x => x.Key);
        }

        protected override IEnumerable<Guid> GetUserSessions(Guid userID)
        {
            return CredentialsCache.GetUserSessions(userID);
        }

        protected override void NotifyAll<TNotification>(TNotification notification)
        {
            foreach(var session in NotifyState.SessionMap.Values)
            {
                session.Connection.WriteAsync(IPCMessage.Notification(notification)).ContinueWith(task =>
                {
                    if(task.Exception != null)
                    {
                        Logger.Send(LogType.Error, "", $"Error in notification: {CoreUtils.FormatException(task.Exception)}");
                    }
                });
            }
        }

        protected override void NotifySession<TNotification>(Guid sessionID, TNotification notification)
        {
            if(NotifyState.SessionMap.TryGetValue(sessionID, out var session))
            {
                session.Connection.WriteAsync(IPCMessage.Notification(notification)).ContinueWith(task =>
                {
                    if(task.Exception != null)
                    {
                        Logger.Send(LogType.Error, "", $"Error in notification: {CoreUtils.FormatException(task.Exception)}");
                    }
                });
            }
        }

        protected override void NotifySession(Guid sessionID, Type TNotification, BaseObject notification)
        {
            if(NotifyState.SessionMap.TryGetValue(sessionID, out var session))
            {
                session.Connection.WriteAsync(IPCMessage.Notification(TNotification, notification)).ContinueWith(task =>
                {
                    if(task.Exception != null)
                    {
                        Logger.Send(LogType.Error, "", $"Error in notification: {CoreUtils.FormatException(task.Exception)}");
                    }
                });
            }
        }
    }
}