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

package com.hypixel.hytale.builtin.asseteditor;

import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorPopupNotificationType;
import com.hypixel.hytale.protocol.packets.connection.DisconnectType;
import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorUpdateWeatherPreviewLockEvent;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.protocol.packets.world.UpdateEditorTimeOverride;
import com.hypixel.hytale.server.core.modules.i18n.I18nModule;
import com.hypixel.hytale.protocol.packets.interface_.UpdateLanguage;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRequestDatasetReply;
import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorRequestDataSetEvent;
import com.hypixel.hytale.event.IEventDispatcher;
import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorActivateButtonEvent;
import com.hypixel.hytale.common.util.CompletableFutureUtil;
import com.hypixel.hytale.protocol.Packet;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchAutoCompleteDataReply;
import com.hypixel.hytale.builtin.asseteditor.event.AssetEditorFetchAutoCompleteDataEvent;
import com.hypixel.hytale.server.core.HytaleServer;
import java.util.concurrent.CompletableFuture;
import java.util.List;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.nio.file.Path;
import java.util.logging.Level;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorDeleteAssetPack;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUpdateAssetPack;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorCreateAssetPack;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUpdateWeatherPreviewLock;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorSetGameTime;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorSubscribeModifiedAssetsChanges;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRedoChanges;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUndoChanges;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchLastModifiedAssets;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorExportAssets;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRenameDirectory;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorDeleteDirectory;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRenameAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorDeleteAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorActivateButton;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchAutoCompleteData;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRequestDataset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorCreateDirectory;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorCreateAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchJsonAssetWithParents;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorFetchAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorSelectAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUpdateJsonAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorUpdateAsset;
import com.hypixel.hytale.protocol.packets.asseteditor.AssetEditorRequestChildrenList;
import com.hypixel.hytale.protocol.packets.connection.Pong;
import com.hypixel.hytale.protocol.packets.connection.Disconnect;
import io.netty.channel.ChannelHandlerContext;
import com.hypixel.hytale.server.core.io.netty.NettyUtil;
import com.hypixel.hytale.protocol.HostAddress;
import java.util.UUID;
import com.hypixel.hytale.server.core.io.PacketHandler;
import com.hypixel.hytale.server.core.auth.PlayerAuthentication;
import com.hypixel.hytale.server.core.io.ProtocolVersion;
import io.netty.channel.Channel;
import javax.annotation.Nonnull;
import com.hypixel.hytale.logger.HytaleLogger;
import com.hypixel.hytale.server.core.io.handlers.GenericPacketHandler;

public class AssetEditorPacketHandler extends GenericPacketHandler
{
    private static final HytaleLogger LOGGER;
    @Nonnull
    private final EditorClient editorClient;
    
    public AssetEditorPacketHandler(@Nonnull final Channel channel, @Nonnull final ProtocolVersion protocolVersion, final String language, @Nonnull final PlayerAuthentication auth) {
        super(channel, protocolVersion);
        this.auth = auth;
        this.editorClient = new EditorClient(language, auth, this);
        this.init();
    }
    
    public AssetEditorPacketHandler(@Nonnull final Channel channel, @Nonnull final ProtocolVersion protocolVersion, final String language, final UUID uuid, final String username) {
        this(channel, protocolVersion, language, uuid, username, null, null);
    }
    
    public AssetEditorPacketHandler(@Nonnull final Channel channel, @Nonnull final ProtocolVersion protocolVersion, final String language, final UUID uuid, final String username, final byte[] referralData, final HostAddress referralSource) {
        super(channel, protocolVersion);
        this.auth = null;
        this.editorClient = new EditorClient(language, uuid, username, this);
        this.init();
    }
    
    private void init() {
        this.registerHandlers();
        AssetEditorPlugin.get().handleInitializeClient(this.editorClient);
    }
    
    @Nonnull
    public EditorClient getEditorClient() {
        return this.editorClient;
    }
    
    @Nonnull
    @Override
    public String getIdentifier() {
        return "{Editor(" + NettyUtil.formatRemoteAddress(this.channel) + "), " + String.valueOf(this.editorClient.getUuid()) + ", " + this.editorClient.getUsername();
    }
    
    @Override
    public void closed(final ChannelHandlerContext ctx) {
        AssetEditorPlugin.get().handleEditorClientDisconnected(this.editorClient, this.disconnectReason);
    }
    
    public void registerHandlers() {
        this.registerHandler(1, p -> this.handle((Disconnect)p));
        this.registerHandler(3, p -> this.handlePong((Pong)p));
        this.registerHandler(321, p -> this.handle((AssetEditorRequestChildrenList)p));
        this.registerHandler(324, p -> this.handle((AssetEditorUpdateAsset)p));
        this.registerHandler(323, p -> this.handle((AssetEditorUpdateJsonAsset)p));
        this.registerHandler(336, p -> this.handle((AssetEditorSelectAsset)p));
        this.registerHandler(310, p -> this.handle((AssetEditorFetchAsset)p));
        this.registerHandler(311, p -> this.handle((AssetEditorFetchJsonAssetWithParents)p));
        this.registerHandler(327, p -> this.handle((AssetEditorCreateAsset)p));
        this.registerHandler(307, p -> this.handle((AssetEditorCreateDirectory)p));
        this.registerHandler(333, p -> this.handle((AssetEditorRequestDataset)p));
        this.registerHandler(331, p -> this.handle((AssetEditorFetchAutoCompleteData)p));
        this.registerHandler(335, p -> this.handle((AssetEditorActivateButton)p));
        this.registerHandler(329, p -> this.handle((AssetEditorDeleteAsset)p));
        this.registerHandler(328, p -> this.handle((AssetEditorRenameAsset)p));
        this.registerHandler(308, p -> this.handle((AssetEditorDeleteDirectory)p));
        this.registerHandler(309, p -> this.handle((AssetEditorRenameDirectory)p));
        this.registerHandler(342, p -> this.handle((AssetEditorExportAssets)p));
        this.registerHandler(338, p -> this.handle((AssetEditorFetchLastModifiedAssets)p));
        this.registerHandler(349, p -> this.handle((AssetEditorUndoChanges)p));
        this.registerHandler(350, p -> this.handle((AssetEditorRedoChanges)p));
        this.registerHandler(341, p -> this.handle((AssetEditorSubscribeModifiedAssetsChanges)p));
        this.registerHandler(352, p -> this.handle((AssetEditorSetGameTime)p));
        this.registerHandler(354, p -> this.handle((AssetEditorUpdateWeatherPreviewLock)p));
        this.registerHandler(316, p -> this.handle((AssetEditorCreateAssetPack)p));
        this.registerHandler(315, p -> this.handle((AssetEditorUpdateAssetPack)p));
        this.registerHandler(317, p -> this.handle((AssetEditorDeleteAssetPack)p));
    }
    
    public void handle(@Nonnull final AssetEditorSubscribeModifiedAssetsChanges packet) {
        if (this.lacksPermission()) {
            return;
        }
        if (packet.subscribe) {
            AssetEditorPlugin.get().handleSubscribeToModifiedAssetsChanges(this.editorClient);
        }
        else {
            AssetEditorPlugin.get().handleUnsubscribeFromModifiedAssetsChanges(this.editorClient);
        }
    }
    
    public void handle(@Nonnull final AssetEditorUndoChanges packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s undoing last change", this.editorClient.getUsername());
        AssetEditorPlugin.get().handleUndo(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorRedoChanges packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s redoing last change", this.editorClient.getUsername());
        AssetEditorPlugin.get().handleRedo(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.token);
    }
    
    public void handle(final AssetEditorFetchLastModifiedAssets packet) {
        if (this.lacksPermission()) {
            return;
        }
        AssetEditorPlugin.get().handleFetchLastModifiedAssets(this.editorClient);
    }
    
    public void handle(@Nonnull final AssetEditorExportAssets packet) {
        if (this.lacksPermission()) {
            return;
        }
        final StringBuilder assets = new StringBuilder();
        for (final com.hypixel.hytale.protocol.packets.asseteditor.AssetPath assetPath : packet.paths) {
            if (!assets.isEmpty()) {
                assets.append(", ");
            }
            assets.append(assetPath.toString());
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is exporting: %s", this.editorClient.getUsername(), assets.toString());
        final List<AssetPath> paths = new ObjectArrayList<AssetPath>();
        for (final com.hypixel.hytale.protocol.packets.asseteditor.AssetPath assetPath2 : packet.paths) {
            paths.add(new AssetPath(assetPath2.pack, Path.of(assetPath2.path, new String[0])));
        }
        AssetEditorPlugin.get().handleExportAssets(this.editorClient, paths);
    }
    
    public void handle(@Nonnull final AssetEditorCreateAsset packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is creating asset %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleCreateAsset(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.data, packet.rebuildCaches, packet.buttonId, packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorFetchAsset packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is fetching asset %s, from opened tab: %s", this.editorClient.getUsername(), packet.path, packet.isFromOpenedTab);
        AssetEditorPlugin.get().handleFetchAsset(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorFetchJsonAssetWithParents packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is fetching json asset %s, from opened tab: %s", this.editorClient.getUsername(), packet.path, packet.isFromOpenedTab);
        AssetEditorPlugin.get().handleFetchJsonAssetWithParents(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.isFromOpenedTab, packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorRequestChildrenList packet) {
        if (this.lacksPermission()) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is requesting child ids for %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleRequestChildIds(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])));
    }
    
    public void handle(@Nonnull final AssetEditorUpdateAsset packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s updating asset at %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleAssetUpdate(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.data, packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorUpdateJsonAsset packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s updating json asset at %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleJsonAssetUpdate(this.editorClient, new AssetPath(packet.path.pack, Path.of(packet.path.path, new String[0])), packet.assetType, packet.assetIndex, packet.commands, packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorFetchAutoCompleteData packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        CompletableFutureUtil._catch(HytaleServer.get().getEventBus().dispatchForAsync((Class<? super AssetEditorFetchAutoCompleteDataEvent>)AssetEditorFetchAutoCompleteDataEvent.class, packet.dataset).dispatch(new AssetEditorFetchAutoCompleteDataEvent(this.editorClient, packet.dataset, packet.query)).thenAccept(event -> {
            if (event.getResults() == null) {
                HytaleLogger.getLogger().at(Level.WARNING).log("Tried to request unknown autocomplete dataset for asset editor: %s", packet.dataset);
            }
            else {
                this.editorClient.getPacketHandler().write(new AssetEditorFetchAutoCompleteDataReply(packet.token, event.getResults()));
            }
        }));
    }
    
    public void handle(@Nonnull final AssetEditorRenameAsset packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.WARNING).log("%s is renaming %s to %s", this.editorClient.getUsername(), packet.path, packet.newPath);
        AssetEditorPlugin.get().handleRenameAsset(this.editorClient, new AssetPath(packet.path), new AssetPath(packet.newPath), packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorDeleteAsset packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is deleting asset %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleDeleteAsset(this.editorClient, new AssetPath(packet.path), packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorActivateButton packet) {
        if (this.lacksPermission()) {
            return;
        }
        AssetEditorPlugin.get().getLogger().at(Level.INFO).log("%s is activating button %s", this.editorClient.getUsername(), packet.buttonId);
        final IEventDispatcher<AssetEditorActivateButtonEvent, AssetEditorActivateButtonEvent> dispatch = HytaleServer.get().getEventBus().dispatchFor((Class<? super AssetEditorActivateButtonEvent>)AssetEditorActivateButtonEvent.class, packet.buttonId);
        if (dispatch.hasListener()) {
            dispatch.dispatch(new AssetEditorActivateButtonEvent(this.editorClient, packet.buttonId));
        }
    }
    
    public void handle(@Nonnull final AssetEditorRequestDataset packet) {
        if (this.lacksPermission()) {
            return;
        }
        CompletableFutureUtil._catch(HytaleServer.get().getEventBus().dispatchForAsync((Class<? super AssetEditorRequestDataSetEvent>)AssetEditorRequestDataSetEvent.class, packet.name).dispatch(new AssetEditorRequestDataSetEvent(this.editorClient, packet.name, null)).thenAccept(event -> {
            if (event.getResults() == null) {
                HytaleLogger.getLogger().at(Level.WARNING).log("Tried to request unknown dataset list for asset editor: %s", packet.name);
            }
            else {
                this.editorClient.getPacketHandler().write(new AssetEditorRequestDatasetReply(packet.name, event.getResults()));
            }
        }));
    }
    
    public void handle(@Nonnull final AssetEditorSelectAsset packet) {
        if (this.lacksPermission()) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s selecting %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleSelectAsset(this.editorClient, (packet.path != null) ? new AssetPath(packet.path) : null);
    }
    
    public void handle(@Nonnull final AssetEditorCreateDirectory packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is creating directory %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleCreateDirectory(this.editorClient, new AssetPath(packet.path), packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorDeleteDirectory packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is deleting directory %s", this.editorClient.getUsername(), packet.path);
        AssetEditorPlugin.get().handleDeleteDirectory(this.editorClient, new AssetPath(packet.path), packet.token);
    }
    
    public void handle(@Nonnull final AssetEditorRenameDirectory packet) {
        if (this.lacksPermission(packet.token)) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is renaming directory %s to $s", this.editorClient.getUsername(), packet.path, packet.newPath);
        AssetEditorPlugin.get().handleRenameDirectory(this.editorClient, new AssetPath(packet.path), new AssetPath(packet.newPath), packet.token);
    }
    
    public void handle(@Nonnull final UpdateLanguage packet) {
        if (this.lacksPermission()) {
            return;
        }
        this.editorClient.setLanguage(packet.language);
        I18nModule.get().sendTranslations(this.editorClient.getPacketHandler(), this.editorClient.getLanguage());
    }
    
    public void handle(@Nonnull final AssetEditorSetGameTime packet) {
        if (this.lacksPermission()) {
            return;
        }
        final PlayerRef player = this.editorClient.tryGetPlayer();
        if (player == null) {
            return;
        }
        player.getPacketHandler().write(new UpdateEditorTimeOverride(packet.gameTime, packet.paused));
    }
    
    public void handle(@Nonnull final AssetEditorUpdateWeatherPreviewLock packet) {
        if (this.lacksPermission()) {
            return;
        }
        final IEventDispatcher<AssetEditorUpdateWeatherPreviewLockEvent, AssetEditorUpdateWeatherPreviewLockEvent> dispatch = HytaleServer.get().getEventBus().dispatchFor((Class<? super AssetEditorUpdateWeatherPreviewLockEvent>)AssetEditorUpdateWeatherPreviewLockEvent.class);
        if (dispatch.hasListener()) {
            dispatch.dispatch(new AssetEditorUpdateWeatherPreviewLockEvent(this.editorClient, packet.locked));
        }
    }
    
    public void handle(@Nonnull final AssetEditorUpdateAssetPack packet) {
        if (this.lacksPermission("hytale.editor.packs.edit")) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is updating the asset pack manifest for %s", this.editorClient.getUsername(), packet.id);
        AssetEditorPlugin.get().handleUpdateAssetPack(this.editorClient, packet.id, packet.manifest);
    }
    
    public void handle(@Nonnull final AssetEditorDeleteAssetPack packet) {
        if (this.lacksPermission("hytale.editor.packs.delete")) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is deleting the asset pack %s", this.editorClient.getUsername(), packet.id);
        AssetEditorPlugin.get().handleDeleteAssetPack(this.editorClient, packet.id);
    }
    
    public void handle(@Nonnull final AssetEditorCreateAssetPack packet) {
        if (this.lacksPermission(packet.token, "hytale.editor.packs.create")) {
            return;
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s is creating a new asset pack: %s:%s", this.editorClient.getUsername(), packet.manifest.group, packet.manifest.name);
        AssetEditorPlugin.get().handleCreateAssetPack(this.editorClient, packet.manifest, packet.token);
    }
    
    public void handle(@Nonnull final Disconnect packet) {
        switch (packet.type) {
            case Disconnect: {
                this.disconnectReason.setClientDisconnectType(DisconnectType.Disconnect);
                break;
            }
            case Crash: {
                this.disconnectReason.setClientDisconnectType(DisconnectType.Crash);
                break;
            }
        }
        AssetEditorPacketHandler.LOGGER.at(Level.INFO).log("%s - %s at %s left with reason: %s - %s", this.editorClient.getUuid(), this.editorClient.getUsername(), NettyUtil.formatRemoteAddress(this.channel), packet.type.name(), packet.reason);
        this.channel.close();
    }
    
    private boolean lacksPermission(final int token) {
        if (!this.editorClient.hasPermission("hytale.editor.asset")) {
            this.editorClient.sendFailureReply(token, Messages.USAGE_DENIED_MESSAGE);
            return true;
        }
        return false;
    }
    
    private boolean lacksPermission() {
        return this.lacksPermission("hytale.editor.asset");
    }
    
    private boolean lacksPermission(final String permissionId) {
        if (!this.editorClient.hasPermission(permissionId)) {
            this.editorClient.sendPopupNotification(AssetEditorPopupNotificationType.Error, Messages.USAGE_DENIED_MESSAGE);
            return true;
        }
        return false;
    }
    
    private boolean lacksPermission(final int token, final String permissionId) {
        if (!this.editorClient.hasPermission(permissionId)) {
            this.editorClient.sendFailureReply(token, Messages.USAGE_DENIED_MESSAGE);
            return true;
        }
        return false;
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
