using InABox.API;
using InABox.Core;

namespace InABox.IPC
{
    public class IPCPusher : IPusher
    {
        IPCPushState PushState { get; set; }

        public IPCPusher(IPCPushState pushState)
        {
            PushState = pushState;
            PushState.OnPoll += PushState_OnPoll;
        }

        private void PushState_OnPoll(IPCPushState.Session session)
        {
            PushManager.Poll(session.SessionID);
        }

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

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

        public void PushToAll<TPush>(TPush push) where TPush : BaseObject
        {
            foreach(var session in PushState.SessionMap.Values)
            {
                session.Connection.WriteAsync(IPCMessage.Push(push)).ContinueWith(task =>
                {
                    if(task.Exception != null)
                    {
                        Logger.Send(LogType.Error, "", $"Error in push: {CoreUtils.FormatException(task.Exception)}");
                    }
                });
            }
        }

        public void PushToSession<TPush>(Guid sessionID, TPush push) where TPush : BaseObject
        {
            if(PushState.SessionMap.TryGetValue(sessionID, out var session))
            {
                session.Connection.WriteAsync(IPCMessage.Push(push)).ContinueWith(task =>
                {
                    if(task.Exception != null)
                    {
                        Logger.Send(LogType.Error, "", $"Error in push: {CoreUtils.FormatException(task.Exception)}");
                    }
                });
            }
        }

        public void PushToSession(Guid sessionID, Type TPush, BaseObject push)
        {
            if(PushState.SessionMap.TryGetValue(sessionID, out var session))
            {
                session.Connection.WriteAsync(IPCMessage.Push(TPush, push)).ContinueWith(task =>
                {
                    if(task.Exception != null)
                    {
                        Logger.Send(LogType.Error, "", $"Error in push: {CoreUtils.FormatException(task.Exception)}");
                    }
                });
            }
        }
    }
}