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

package com.hypixel.hytale.builtin.crafting.window;

import java.lang.invoke.CallSite;
import java.lang.reflect.UndeclaredThrowableException;
import java.lang.invoke.MethodHandle;
import java.lang.runtime.SwitchBootstraps;
import java.lang.invoke.MethodType;
import java.lang.invoke.MethodHandles;
import com.hypixel.hytale.server.core.inventory.container.ItemContainer;
import com.hypixel.hytale.builtin.crafting.CraftingPlugin;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.Bench;
import com.hypixel.hytale.server.core.inventory.Inventory;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.universe.world.meta.BlockState;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.SoundUtil;
import com.hypixel.hytale.protocol.SoundCategory;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.builtin.crafting.component.CraftingManager;
import com.hypixel.hytale.protocol.packets.window.TierUpgradeAction;
import com.hypixel.hytale.protocol.packets.window.SetActiveAction;
import java.util.Objects;
import com.hypixel.hytale.math.util.ChunkUtil;
import com.hypixel.hytale.protocol.packets.window.WindowAction;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import java.util.Iterator;
import java.util.Collection;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.asset.type.item.config.CraftingRecipe;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonArray;
import com.hypixel.hytale.server.core.asset.type.blocktype.config.bench.ProcessingBench;
import java.util.HashSet;
import com.hypixel.hytale.builtin.crafting.state.BenchState;
import com.hypixel.hytale.protocol.packets.window.WindowType;
import com.hypixel.hytale.builtin.crafting.state.ProcessingBenchState;
import java.util.Set;
import javax.annotation.Nullable;
import com.hypixel.hytale.event.EventRegistration;
import com.hypixel.hytale.server.core.inventory.container.CombinedItemContainer;
import com.hypixel.hytale.server.core.entity.entities.player.windows.ItemContainerWindow;

public class ProcessingBenchWindow extends BenchWindow implements ItemContainerWindow
{
    private CombinedItemContainer itemContainer;
    @Nullable
    private EventRegistration<?, ?> inventoryRegistration;
    private float fuelTime;
    private int maxFuel;
    private float progress;
    private boolean active;
    private final Set<Short> processingSlots;
    private final Set<Short> processingFuelSlots;
    
    public ProcessingBenchWindow(final ProcessingBenchState benchState) {
        super(WindowType.Processing, benchState);
        this.processingSlots = new HashSet<Short>();
        this.processingFuelSlots = new HashSet<Short>();
        final ProcessingBench processingBench = (ProcessingBench)this.blockType.getBench();
        final CraftingRecipe recipe = benchState.getRecipe();
        final float inputProgress = benchState.getInputProgress();
        final float progress = (recipe != null && recipe.getTimeSeconds() > 0.0f) ? (inputProgress / recipe.getTimeSeconds()) : 0.0f;
        this.itemContainer = benchState.getItemContainer();
        this.active = benchState.isActive();
        this.progress = progress;
        this.windowData.addProperty("active", this.active);
        this.windowData.addProperty("progress", progress);
        if (processingBench.getFuel() != null && processingBench.getFuel().length > 0) {
            final JsonArray fuelArray = new JsonArray();
            for (final ProcessingBench.ProcessingSlot benchSlot : processingBench.getFuel()) {
                final JsonObject fuelObj = new JsonObject();
                fuelObj.addProperty("icon", benchSlot.getIcon());
                fuelObj.addProperty("resourceTypeId", benchSlot.getResourceTypeId());
                fuelArray.add(fuelObj);
            }
            this.windowData.add("fuel", fuelArray);
        }
        if (processingBench.getMaxFuel() > 0) {
            this.maxFuel = processingBench.getMaxFuel();
        }
        this.windowData.addProperty("maxFuel", this.maxFuel);
        this.windowData.addProperty("fuelTime", this.fuelTime);
        this.windowData.addProperty("progress", progress);
        this.windowData.addProperty("processingFuelSlots", 0);
        this.windowData.addProperty("processingSlots", 0);
        final int tierLevel = this.getBenchTierLevel();
        this.updateInputSlots(tierLevel);
        this.updateOutputSlots(tierLevel);
    }
    
    @Nonnull
    @Override
    public JsonObject getData() {
        return this.windowData;
    }
    
    @Nonnull
    @Override
    public CombinedItemContainer getItemContainer() {
        return this.itemContainer;
    }
    
    public void setActive(final boolean active) {
        if (this.active != active) {
            this.active = active;
            this.windowData.addProperty("active", active);
            this.invalidate();
        }
    }
    
    public void setFuelTime(final float fuelTime) {
        if (Float.isInfinite(fuelTime)) {
            throw new IllegalArgumentException("Infinite fuelTime");
        }
        if (Float.isNaN(fuelTime)) {
            throw new IllegalArgumentException("Nan fuelTime");
        }
        if (this.fuelTime != fuelTime) {
            this.fuelTime = fuelTime;
            this.windowData.addProperty("fuelTime", fuelTime);
            this.invalidate();
        }
    }
    
    public void setMaxFuel(final int maxFuel) {
        this.maxFuel = maxFuel;
        this.windowData.addProperty("maxFuel", maxFuel);
        this.invalidate();
    }
    
    public void setProgress(final float progress) {
        if (Float.isInfinite(progress)) {
            throw new IllegalArgumentException("Infinite progress");
        }
        if (Float.isNaN(progress)) {
            throw new IllegalArgumentException("Nan fuelTime");
        }
        if (this.progress != progress) {
            this.progress = progress;
            this.windowData.addProperty("progress", progress);
            this.invalidate();
        }
    }
    
    public void setProcessingSlots(final Set<Short> slots) {
        if (this.processingSlots.equals(slots)) {
            return;
        }
        this.processingSlots.clear();
        this.processingSlots.addAll(slots);
        int bitMask = 0;
        for (final Short processingSlot : slots) {
            bitMask |= 1 << processingSlot;
        }
        this.windowData.addProperty("processingSlots", (byte)bitMask);
        this.invalidate();
    }
    
    public void setProcessingFuelSlots(final Set<Short> slots) {
        if (this.processingFuelSlots.equals(slots)) {
            return;
        }
        this.processingFuelSlots.clear();
        this.processingFuelSlots.addAll(slots);
        int bitMask = 0;
        for (final Short processingFuelSlots : slots) {
            bitMask |= 1 << processingFuelSlots;
        }
        this.windowData.addProperty("processingFuelSlots", (byte)bitMask);
        this.invalidate();
    }
    
    @Override
    public void handleAction(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final WindowAction action) {
        final World world = store.getExternalData().getWorld();
        final BlockState blockState = world.getChunk(ChunkUtil.indexChunkFromBlock(this.x, this.z)).getState(this.x, this.y, this.z);
        if (blockState instanceof final ProcessingBenchState benchState) {
            Objects.requireNonNull(action);
            switch (/* invokedynamic(!) */ProcyonInvokeDynamicHelper_14.invoke(action, false)) {
                case 0: {
                    final SetActiveAction setActiveAction = (SetActiveAction)action;
                    if (!benchState.setActive(setActiveAction.state)) {
                        this.invalidate();
                        break;
                    }
                    break;
                }
                case 1: {
                    final TierUpgradeAction ignored = (TierUpgradeAction)action;
                    final CraftingManager craftingManager = store.getComponent(ref, CraftingManager.getComponentType());
                    if (craftingManager == null) {
                        return;
                    }
                    if (craftingManager.startTierUpgrade(ref, store, this) && this.bench.getBenchUpgradeSoundEventIndex() != 0) {
                        SoundUtil.playSoundEvent3d(this.bench.getBenchUpgradeSoundEventIndex(), SoundCategory.SFX, this.x + 0.5, this.y + 0.5, this.z + 0.5, store);
                    }
                    break;
                }
            }
        }
    }
    
    @Override
    protected boolean onOpen0(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store) {
        super.onOpen0(ref, store);
        final Player playerComponent = store.getComponent(ref, Player.getComponentType());
        assert playerComponent != null;
        final Inventory inventory = playerComponent.getInventory();
        this.inventoryRegistration = inventory.getCombinedHotbarFirst().registerChangeEvent(event -> {
            this.windowData.add("inventoryHints", generateInventoryHints(this.bench, inventory.getCombinedHotbarFirst()));
            this.invalidate();
            return;
        });
        this.windowData.add("inventoryHints", generateInventoryHints(this.bench, inventory.getCombinedHotbarFirst()));
        return true;
    }
    
    private void updateOutputSlots(final int tierLevel) {
        this.windowData.addProperty("outputSlotsCount", ((ProcessingBench)this.blockType.getBench()).getOutputSlotsCount(tierLevel));
    }
    
    private void updateInputSlots(final int tierLevel) {
        final ProcessingBench.ProcessingSlot[] input = ((ProcessingBench)this.blockType.getBench()).getInput(tierLevel);
        if (input != null && input.length > 0) {
            final JsonArray inputArr = new JsonArray();
            for (final ProcessingBench.ProcessingSlot benchSlot : input) {
                if (benchSlot != null) {
                    final JsonObject slotObj = new JsonObject();
                    slotObj.addProperty("icon", benchSlot.getIcon());
                    inputArr.add(slotObj);
                }
            }
            this.windowData.add("input", inputArr);
        }
    }
    
    @Override
    public void updateBenchTierLevel(final int newValue) {
        super.updateBenchTierLevel(newValue);
        this.updateInputSlots(newValue);
        this.updateOutputSlots(newValue);
        final BenchState benchState = this.benchState;
        if (benchState instanceof final ProcessingBenchState processingBenchState) {
            this.itemContainer = processingBenchState.getItemContainer();
        }
    }
    
    @Override
    public void onClose0(@Nonnull final Ref<EntityStore> ref, @Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        super.onClose0(ref, componentAccessor);
        if (this.inventoryRegistration != null) {
            this.inventoryRegistration.unregister();
            this.inventoryRegistration = null;
        }
    }
    
    @Nonnull
    private static JsonArray generateInventoryHints(@Nonnull final Bench bench, @Nonnull final CombinedItemContainer combinedInputItemContainer) {
        return CraftingManager.generateInventoryHints(CraftingPlugin.getBenchRecipes(bench), 0, combinedInputItemContainer);
    }
    
    // This helper class was generated by Procyon to approximate the behavior of an
    // 'invokedynamic' instruction that it doesn't know how to interpret.
    private static final class ProcyonInvokeDynamicHelper_14
    {
        private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
        private static MethodHandle handle;
        private static volatile int fence;
        
        private static MethodHandle handle() {
            final MethodHandle handle = ProcyonInvokeDynamicHelper_14.handle;
            if (handle != null)
                return handle;
            return ProcyonInvokeDynamicHelper_14.ensureHandle();
        }
        
        private static MethodHandle ensureHandle() {
            ProcyonInvokeDynamicHelper_14.fence = 0;
            MethodHandle handle = ProcyonInvokeDynamicHelper_14.handle;
            if (handle == null) {
                MethodHandles.Lookup lookup = ProcyonInvokeDynamicHelper_14.LOOKUP;
                try {
                    handle = ((CallSite)SwitchBootstraps.typeSwitch(lookup, "typeSwitch", MethodType.methodType(int.class, Object.class, int.class), SetActiveAction.class, TierUpgradeAction.class)).dynamicInvoker();
                }
                catch (Throwable t) {
                    throw new UndeclaredThrowableException(t);
                }
                ProcyonInvokeDynamicHelper_14.fence = 1;
                ProcyonInvokeDynamicHelper_14.handle = handle;
                ProcyonInvokeDynamicHelper_14.fence = 0;
            }
            return handle;
        }
        
        private static int invoke(Object p0, int p1) {
            try {
                return ProcyonInvokeDynamicHelper_14.handle().invokeExact(p0, p1);
            }
            catch (Throwable t) {
                throw new UndeclaredThrowableException(t);
            }
        }
    }
}
