// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.io.adapter;

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.protocol.Packet;
import com.hypixel.hytale.server.core.io.PacketHandler;
import com.hypixel.hytale.server.core.io.handlers.game.GamePacketHandler;
import javax.annotation.Nonnull;
import java.util.List;

public class PacketAdapters
{
    private static final List<PacketFilter> inboundHandlers;
    private static final List<PacketFilter> outboundHandlers;
    
    @Nonnull
    public static PacketFilter registerInbound(@Nonnull final PacketWatcher watcher) {
        final PacketFilter out = (packetListener, packet) -> {
            watcher.accept(packetListener, packet);
            return false;
        };
        registerInbound(out);
        return out;
    }
    
    public static void registerInbound(final PacketFilter predicate) {
        PacketAdapters.inboundHandlers.add(predicate);
    }
    
    @Nonnull
    public static PacketFilter registerOutbound(@Nonnull final PacketWatcher watcher) {
        final PacketFilter out = (packetListener, packet) -> {
            watcher.accept(packetListener, packet);
            return false;
        };
        registerOutbound(out);
        return out;
    }
    
    public static void registerOutbound(final PacketFilter predicate) {
        PacketAdapters.outboundHandlers.add(predicate);
    }
    
    @Nonnull
    public static PacketFilter registerInbound(@Nonnull final PlayerPacketFilter filter) {
        final PacketFilter out = (packetHandler, client) -> packetHandler instanceof GamePacketHandler && filter.test(((GamePacketHandler)packetHandler).getPlayerRef(), client);
        registerInbound(out);
        return out;
    }
    
    @Nonnull
    public static PacketFilter registerOutbound(@Nonnull final PlayerPacketFilter filter) {
        final PacketFilter out = (packetHandler, server) -> packetHandler instanceof GamePacketHandler && filter.test(((GamePacketHandler)packetHandler).getPlayerRef(), server);
        registerOutbound(out);
        return out;
    }
    
    @Nonnull
    public static PacketFilter registerInbound(@Nonnull final PlayerPacketWatcher watcher) {
        final PacketFilter out = (packetHandler, client) -> {
            if (packetHandler instanceof final GamePacketHandler gamePacketHandler) {
                watcher.accept(gamePacketHandler.getPlayerRef(), client);
            }
            return false;
        };
        registerInbound(out);
        return out;
    }
    
    @Nonnull
    public static PacketFilter registerOutbound(@Nonnull final PlayerPacketWatcher watcher) {
        final PacketFilter out = (packetHandler, server) -> {
            if (packetHandler instanceof final GamePacketHandler gamePacketHandler) {
                watcher.accept(gamePacketHandler.getPlayerRef(), server);
            }
            return false;
        };
        registerOutbound(out);
        return out;
    }
    
    public static void deregisterInbound(final PacketFilter predicate) {
        if (!PacketAdapters.inboundHandlers.remove(predicate)) {
            throw new IllegalArgumentException("That handler was not registered to inbound!");
        }
    }
    
    public static void deregisterOutbound(final PacketFilter predicate) {
        if (!PacketAdapters.outboundHandlers.remove(predicate)) {
            throw new IllegalArgumentException("That handler was not registered to outbound!");
        }
    }
    
    public static boolean __handleInbound(final PacketHandler player, final Packet packet) {
        return handle(PacketAdapters.inboundHandlers, player, packet);
    }
    
    private static <T extends Packet> boolean handle(@Nonnull final List<PacketFilter> list, final PacketHandler player, final T packet) {
        for (int i = 0; i < list.size(); ++i) {
            try {
                if (list.get(i).test(player, (Packet)packet)) {
                    return true;
                }
            }
            catch (final Throwable t) {
                HytaleLogger.getLogger().at(Level.SEVERE).withCause(t).log("Failed to test packet %s against %s:", packet, player);
            }
        }
        return false;
    }
    
    public static boolean __handleOutbound(final PacketHandler player, final Packet packet) {
        return handle(PacketAdapters.outboundHandlers, player, packet);
    }
    
    static {
        inboundHandlers = new CopyOnWriteArrayList<PacketFilter>();
        outboundHandlers = new CopyOnWriteArrayList<PacketFilter>();
    }
}
