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

package com.hypixel.hytale.server.core.modules.accesscontrol;

import java.util.concurrent.CompletionStage;
import java.util.UUID;
import com.hypixel.hytale.server.core.modules.accesscontrol.ban.Ban;
import com.google.gson.JsonObject;
import java.util.concurrent.CompletableFuture;
import java.util.Optional;
import com.hypixel.hytale.server.core.event.events.player.PlayerSetupConnectEvent;
import com.hypixel.hytale.server.core.modules.accesscontrol.ban.InfiniteBan;
import com.hypixel.hytale.server.core.modules.accesscontrol.ban.TimedBan;
import com.hypixel.hytale.server.core.modules.accesscontrol.commands.WhitelistCommand;
import com.hypixel.hytale.server.core.modules.accesscontrol.commands.UnbanCommand;
import com.hypixel.hytale.server.core.command.system.AbstractCommand;
import com.hypixel.hytale.server.core.modules.accesscontrol.commands.BanCommand;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
import com.hypixel.hytale.server.core.modules.accesscontrol.ban.BanParser;
import java.util.Map;
import com.hypixel.hytale.server.core.modules.accesscontrol.provider.AccessProvider;
import java.util.List;
import com.hypixel.hytale.server.core.modules.accesscontrol.provider.HytaleBanProvider;
import com.hypixel.hytale.server.core.modules.accesscontrol.provider.HytaleWhitelistProvider;
import com.hypixel.hytale.common.plugin.PluginManifest;
import com.hypixel.hytale.server.core.plugin.JavaPlugin;

public class AccessControlModule extends JavaPlugin
{
    public static final PluginManifest MANIFEST;
    private static AccessControlModule instance;
    private final HytaleWhitelistProvider whitelistProvider;
    private final HytaleBanProvider banProvider;
    private final List<AccessProvider> providerRegistry;
    private final Map<String, BanParser> parsers;
    
    public static AccessControlModule get() {
        return AccessControlModule.instance;
    }
    
    public AccessControlModule(@Nonnull final JavaPluginInit init) {
        super(init);
        this.whitelistProvider = new HytaleWhitelistProvider();
        this.banProvider = new HytaleBanProvider();
        this.providerRegistry = new CopyOnWriteArrayList<AccessProvider>() {
            {
                ((CopyOnWriteArrayList<HytaleWhitelistProvider>)this).add(AccessControlModule.this.whitelistProvider);
                ((CopyOnWriteArrayList<HytaleBanProvider>)this).add(AccessControlModule.this.banProvider);
            }
        };
        this.parsers = new ConcurrentHashMap<String, BanParser>();
        AccessControlModule.instance = this;
    }
    
    @Override
    protected void setup() {
        this.getCommandRegistry().registerCommand(new BanCommand(this.banProvider));
        this.getCommandRegistry().registerCommand(new UnbanCommand(this.banProvider));
        this.getCommandRegistry().registerCommand(new WhitelistCommand(this.whitelistProvider));
        this.registerBanParser("timed", TimedBan::fromJsonObject);
        this.registerBanParser("infinite", InfiniteBan::fromJsonObject);
        this.getEventRegistry().register(PlayerSetupConnectEvent.class, event -> {
            final CompletableFuture<Optional<String>> completableFuture = this.getDisconnectReason(event.getUuid());
            final Optional<String> disconnectReason = completableFuture.join();
            if (disconnectReason.isPresent()) {
                event.setReason(disconnectReason.get());
                event.setCancelled(true);
            }
        });
    }
    
    @Override
    protected void start() {
        this.whitelistProvider.syncLoad();
        this.banProvider.syncLoad();
    }
    
    @Override
    protected void shutdown() {
        this.whitelistProvider.syncSave();
        this.banProvider.syncSave();
    }
    
    public void registerBanParser(final String type, final BanParser banParser) {
        final BanParser currentParser = this.parsers.get(type);
        if (currentParser != null) {
            throw new IllegalArgumentException("Type \"" + type + "\" is already registered by " + String.valueOf(currentParser.getClass()));
        }
        this.parsers.put(type, banParser);
    }
    
    public void registerAccessProvider(final AccessProvider provider) {
        this.providerRegistry.add(provider);
    }
    
    public Ban parseBan(final String type, final JsonObject object) {
        final BanParser parser = this.parsers.get(type);
        if (parser == null) {
            throw new IllegalArgumentException("No BanParser for type: " + type);
        }
        return parser.parse(object);
    }
    
    @Nonnull
    private CompletableFuture<Optional<String>> getDisconnectReason(final UUID uuid) {
        return this.providerRegistry.stream().map(p -> p.getDisconnectReason(uuid)).reduce((CompletableFuture<Optional<String>>)CompletableFuture.completedFuture(Optional.empty()), (a, b) -> a.thenCombine((CompletionStage)b, (aMessage, bMessage) -> {
            if (aMessage.isPresent()) {
                return aMessage;
            }
            else if (bMessage.isPresent()) {
                return bMessage;
            }
            else {
                return Optional.empty();
            }
        }));
    }
    
    static {
        MANIFEST = PluginManifest.corePlugin(AccessControlModule.class).build();
    }
}
