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

package com.hypixel.hytale.builtin.adventure.memories.page;

import com.hypixel.hytale.codec.codecs.EnumCodec;
import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import java.time.temporal.TemporalAccessor;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.Instant;
import java.util.Locale;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import com.hypixel.hytale.builtin.adventure.memories.memories.npc.NPCMemory;
import it.unimi.dsi.fastutil.objects.ObjectList;
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.server.core.universe.world.ParticleUtil;
import java.util.List;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.component.spatial.SpatialResource;
import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent;
import com.hypixel.hytale.server.core.entity.entities.Player;
import com.hypixel.hytale.server.core.ui.Value;
import com.hypixel.hytale.server.core.ui.Anchor;
import com.hypixel.hytale.builtin.adventure.memories.MemoriesGameplayConfig;
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
import com.hypixel.hytale.server.core.asset.type.gameplay.GameplayConfig;
import java.util.Iterator;
import java.util.function.Function;
import java.util.Comparator;
import java.util.Collection;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import com.hypixel.hytale.server.core.Message;
import java.util.Map;
import com.hypixel.hytale.builtin.adventure.memories.component.PlayerMemories;
import com.hypixel.hytale.server.core.ui.builder.EventData;
import com.hypixel.hytale.protocol.packets.interface_.CustomUIEventBindingType;
import java.util.Set;
import com.hypixel.hytale.builtin.adventure.memories.MemoriesPlugin;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
import com.hypixel.hytale.protocol.BlockPosition;
import javax.annotation.Nonnull;
import com.hypixel.hytale.server.core.universe.PlayerRef;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.builtin.adventure.memories.memories.Memory;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.entity.entities.player.pages.InteractiveCustomUIPage;

public class MemoriesPage extends InteractiveCustomUIPage<PageEventData>
{
    @Nullable
    private String currentCategory;
    @Nullable
    private Memory selectedMemory;
    private Vector3d recordMemoriesParticlesPosition;
    
    public MemoriesPage(@Nonnull final PlayerRef playerRef, final BlockPosition blockPosition) {
        super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction, PageEventData.CODEC);
        this.recordMemoriesParticlesPosition = new Vector3d(blockPosition.x, blockPosition.y, blockPosition.z);
    }
    
    @Override
    public void build(@Nonnull final Ref<EntityStore> ref, @Nonnull final UICommandBuilder commandBuilder, @Nonnull final UIEventBuilder eventBuilder, @Nonnull final Store<EntityStore> store) {
        final MemoriesPlugin memoriesPlugin = MemoriesPlugin.get();
        if (this.currentCategory == null) {
            commandBuilder.append("Pages/Memories/MemoriesCategoryPanel.ui");
            final Map<String, Set<Memory>> allMemories = memoriesPlugin.getAllMemories();
            final Set<Memory> recordedMemories = memoriesPlugin.getRecordedMemories();
            int totalMemories = 0;
            for (final Set<Memory> value : allMemories.values()) {
                totalMemories += value.size();
            }
            commandBuilder.set("#MemoriesProgressBar.Value", recordedMemories.size() / (float)totalMemories);
            commandBuilder.set("#MemoriesProgressBarTexture.Value", recordedMemories.size() / (float)totalMemories);
            commandBuilder.set("#TotalCollected.Text", String.valueOf(recordedMemories.size()));
            commandBuilder.set("#MemoriesTotal.Text", String.valueOf(totalMemories));
            eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#MemoriesInfoButton", new EventData().append("Action", PageAction.MemoriesInfo));
            final GameplayConfig gameplayConfig = store.getExternalData().getWorld().getGameplayConfig();
            final PlayerMemories playerMemories = store.getComponent(ref, PlayerMemories.getComponentType());
            int i = 0;
            for (Map.Entry<String, Set<Memory>> entry : allMemories.entrySet()) {
                final String category = entry.getKey();
                final Set<Memory> memoriesInCategory = entry.getValue();
                final String selector = "#IconList[" + i++ + "] ";
                int recordedMemoriesCount = 0;
                for (final Memory memory : memoriesInCategory) {
                    if (recordedMemories.contains(memory)) {
                        ++recordedMemoriesCount;
                    }
                }
                commandBuilder.append("#IconList", "Pages/Memories/MemoriesCategory.ui");
                commandBuilder.set(selector + "#Button.Text", Message.translation("server.memories.categories." + category + ".title"));
                commandBuilder.set(selector + "#CurrentMemoryCountNotComplete.Text", String.valueOf(recordedMemoriesCount));
                commandBuilder.set(selector + "#CurrentMemoryCountComplete.Text", String.valueOf(recordedMemoriesCount));
                commandBuilder.set(selector + "#TotalMemoryCountNotComplete.Text", String.valueOf(memoriesInCategory.size()));
                commandBuilder.set(selector + "#TotalMemoryCountComplete.Text", String.valueOf(memoriesInCategory.size()));
                final boolean isCategoryComplete = recordedMemoriesCount == memoriesInCategory.size();
                if (isCategoryComplete) {
                    commandBuilder.set(selector + "#CategoryIcon.Background", "Pages/Memories/categories/" + category + "Complete.png");
                    commandBuilder.set(selector + "#CompleteCategoryBackground.Visible", true);
                    commandBuilder.set(selector + "#CompleteCategoryCounter.Visible", true);
                }
                else {
                    commandBuilder.set(selector + "#CategoryIcon.Background", "Pages/Memories/categories/" + category + ".png");
                    commandBuilder.set(selector + "#NotCompleteCategoryCounter.Visible", true);
                }
                if (playerMemories != null) {
                    final Set<Memory> newMemories = playerMemories.getRecordedMemories();
                    for (Memory memory2 : memoriesInCategory) {
                        if (newMemories.contains(memory2)) {
                            commandBuilder.set(selector + "#NewMemoryIndicator.Visible", true);
                            break;
                        }
                    }
                }
                eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, selector + "#Button", new EventData().append("Action", PageAction.ViewCategory).append("Category", category));
            }
            commandBuilder.set("#RecordButton.Visible", true);
            commandBuilder.set("#RecordButton.Disabled", playerMemories == null || !playerMemories.hasMemories());
            buildChestMarkers(commandBuilder, gameplayConfig, totalMemories);
            if (playerMemories != null && playerMemories.hasMemories()) {
                commandBuilder.set("#RecordButton.Text", Message.translation("server.memories.general.recordNum").param("count", playerMemories.getRecordedMemories().size()));
            }
            eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#RecordButton", new EventData().append("Action", PageAction.Record));
        }
        else {
            commandBuilder.append("Pages/Memories/MemoriesPanel.ui");
            final Set<Memory> memoriesSet = memoriesPlugin.getAllMemories().get(this.currentCategory);
            final ObjectArrayList<Memory> memories = new ObjectArrayList<Memory>(memoriesSet);
            memories.sort(Comparator.comparing((Function<? super Memory, ? extends Comparable>)Memory::getTitle));
            final Set<Memory> recordedMemories2 = memoriesPlugin.getRecordedMemories();
            int recordedMemoriesCount2 = 0;
            for (final Memory memory3 : memories) {
                if (recordedMemories2.contains(memory3)) {
                    ++recordedMemoriesCount2;
                }
            }
            commandBuilder.set("#CategoryTitle.Text", Message.translation("server.memories.categories." + this.currentCategory + ".title"));
            commandBuilder.set("#CategoryCount.Text", recordedMemoriesCount2 + "/" + memories.size());
            for (int j = 0; j < memories.size(); ++j) {
                final Memory memory3 = memories.get(j);
                final String selector2 = "#IconList[" + j + "] ";
                commandBuilder.append("#IconList", "Pages/Memories/Memory.ui");
                final boolean isDiscovered = recordedMemories2.contains(memory3);
                final boolean isSelected = this.selectedMemory != null && this.selectedMemory.equals(memory3);
                final String buttonSelector = isSelected ? (selector2 + "#ButtonSelected") : (selector2 + "#ButtonNotSelected");
                if (isDiscovered) {
                    commandBuilder.set(buttonSelector + ".Visible", true);
                    commandBuilder.set(buttonSelector + ".TooltipText", memory3.getTooltipText());
                    commandBuilder.setNull(buttonSelector + ".Background");
                    final String iconPath = memory3.getIconPath();
                    if (iconPath != null && !iconPath.isEmpty()) {
                        commandBuilder.set(selector2 + "#Icon.AssetPath", iconPath);
                    }
                    eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, buttonSelector, new EventData().append("Action", PageAction.SelectMemory).append("MemoryId", memory3.getId()));
                }
                else {
                    commandBuilder.set(selector2 + "#EmptyBackground.Visible", true);
                }
            }
            if (this.selectedMemory != null && recordedMemories2.contains(this.selectedMemory)) {
                updateMemoryDetailsPanel(commandBuilder, this.selectedMemory);
            }
            eventBuilder.addEventBinding(CustomUIEventBindingType.Activating, "#BackButton", new EventData().append("Action", PageAction.Back));
        }
    }
    
    private static void buildChestMarkers(@Nonnull final UICommandBuilder commandBuilder, @Nonnull final GameplayConfig gameplayConfig, final int totalMemories) {
        final MemoriesGameplayConfig memoriesConfig = MemoriesGameplayConfig.get(gameplayConfig);
        if (memoriesConfig == null) {
            return;
        }
        final int[] memoriesAmountPerLevel = memoriesConfig.getMemoriesAmountPerLevel();
        if (memoriesAmountPerLevel == null || memoriesAmountPerLevel.length <= 1) {
            return;
        }
        final MemoriesPlugin memoriesPlugin = MemoriesPlugin.get();
        final int recordedMemoriesCount = memoriesPlugin.getRecordedMemories().size();
        final int PROGRESS_BAR_PADDING = 18;
        final int PROGRESS_BAR_WIDTH = 1018;
        final int CHEST_POSITION_AREA = 1000;
        for (int i = 0; i < memoriesAmountPerLevel.length; ++i) {
            final int memoryAmount = memoriesAmountPerLevel[i];
            final boolean hasReachedLevel = recordedMemoriesCount >= memoryAmount;
            final String selector = "#ChestMarkers[" + i;
            final Anchor anchor = new Anchor();
            final int left = memoryAmount * 1000 / totalMemories;
            commandBuilder.append("#ChestMarkers", "Pages/Memories/ChestMarker.ui");
            anchor.setLeft(Value.of(left));
            commandBuilder.setObject(selector + ".Anchor", (Object)anchor);
            final Message rewardsMessage = Message.translation("server.memories.general.chestActive.level" + (i + 1) + ".rewards");
            if (hasReachedLevel) {
                final Message memoriesUnlockedMessage = Message.translation("server.memories.general.chestActive.tooltipText").param("count", memoryAmount);
                final Message activeTooltipMessage = memoriesUnlockedMessage.insert("\n").insert(rewardsMessage);
                commandBuilder.set(selector + " #Arrow.Visible", true);
                commandBuilder.set(selector + " #ChestActive.Visible", true);
                commandBuilder.set(selector + " #ChestActive.TooltipTextSpans", activeTooltipMessage);
            }
            else {
                commandBuilder.set(selector + " #ChestDisabled.Visible", true);
                final Message memoriesToUnlockMessage = Message.translation("server.memories.general.chestLocked.tooltipText").param("count", memoryAmount);
                final Message disabledTooltipMessage = memoriesToUnlockMessage.insert("\n").insert(rewardsMessage);
                commandBuilder.set(selector + " #ChestDisabled.TooltipTextSpans", disabledTooltipMessage);
            }
        }
    }
    
    @Override
    public void handleDataEvent(@Nonnull final Ref<EntityStore> ref, @Nonnull final Store<EntityStore> store, @Nonnull final PageEventData data) {
        final Player player = store.getComponent(ref, Player.getComponentType());
        assert player != null;
        final TransformComponent transformComponent = store.getComponent(ref, TransformComponent.getComponentType());
        assert transformComponent != null;
        switch (data.action.ordinal()) {
            case 0: {
                final PlayerMemories playerMemories = store.getComponent(ref, PlayerMemories.getComponentType());
                if (playerMemories == null) {
                    this.sendUpdate();
                    return;
                }
                if (!MemoriesPlugin.get().recordPlayerMemories(playerMemories)) {
                    this.rebuild();
                    return;
                }
                final MemoriesGameplayConfig memoriesGameplayConfig = MemoriesGameplayConfig.get(store.getExternalData().getWorld().getGameplayConfig());
                if (memoriesGameplayConfig != null) {
                    final SpatialResource<Ref<EntityStore>, EntityStore> playerSpatialResource = store.getResource(EntityModule.get().getPlayerSpatialResourceType());
                    final ObjectList<Ref<EntityStore>> results = SpatialResource.getThreadLocalReferenceList();
                    playerSpatialResource.getSpatialStructure().collect(this.recordMemoriesParticlesPosition, 75.0, results);
                    ParticleUtil.spawnParticleEffect(memoriesGameplayConfig.getMemoriesRecordParticles(), this.recordMemoriesParticlesPosition, results, store);
                }
                this.close();
                break;
            }
            case 1: {
                this.currentCategory = data.category;
                this.selectedMemory = null;
                this.rebuild();
                break;
            }
            case 2: {
                this.currentCategory = null;
                this.selectedMemory = null;
                this.rebuild();
                break;
            }
            case 3: {
                final BlockPosition blockPostion = new BlockPosition((int)this.recordMemoriesParticlesPosition.x, (int)this.recordMemoriesParticlesPosition.y, (int)this.recordMemoriesParticlesPosition.z);
                player.getPageManager().openCustomPage(ref, store, new MemoriesUnlockedPage(this.playerRef, blockPostion));
                break;
            }
            case 4: {
                if (data.memoryId == null || this.currentCategory == null) {
                    return;
                }
                final Set<Memory> memoriesSet = MemoriesPlugin.get().getAllMemories().get(this.currentCategory);
                if (memoriesSet == null) {
                    return;
                }
                final ObjectArrayList<Memory> memories = new ObjectArrayList<Memory>(memoriesSet);
                memories.sort(Comparator.comparing((Function<? super Memory, ? extends Comparable>)Memory::getTitle));
                final Set<Memory> recordedMemories = MemoriesPlugin.get().getRecordedMemories();
                if (recordedMemories == null) {
                    return;
                }
                Memory newSelection = null;
                for (final Memory memory : recordedMemories) {
                    if (memory.getId().equals(data.memoryId)) {
                        newSelection = memory;
                        break;
                    }
                }
                if (newSelection == null) {
                    return;
                }
                if (!memories.contains(newSelection) || newSelection.equals(this.selectedMemory)) {
                    return;
                }
                final UICommandBuilder commandBuilder = new UICommandBuilder();
                if (this.selectedMemory != null && recordedMemories.contains(this.selectedMemory)) {
                    final int previousIndex = memories.indexOf(this.selectedMemory);
                    if (previousIndex >= 0) {
                        updateMemoryButtonSelection(commandBuilder, previousIndex, this.selectedMemory, false);
                    }
                }
                final int newIndex = memories.indexOf(newSelection);
                if (newIndex >= 0) {
                    updateMemoryButtonSelection(commandBuilder, newIndex, newSelection, true);
                }
                updateMemoryDetailsPanel(commandBuilder, newSelection);
                this.selectedMemory = newSelection;
                this.sendUpdate(commandBuilder);
                break;
            }
        }
    }
    
    private static void updateMemoryButtonSelection(@Nonnull final UICommandBuilder commandBuilder, final int index, @Nonnull final Memory memory, final boolean isSelected) {
        final String selector = "#IconList[" + index + "] ";
        if (isSelected) {
            commandBuilder.set(selector + "#ButtonNotSelected.Visible", false);
            commandBuilder.set(selector + "#ButtonSelected.Visible", true);
            commandBuilder.setNull(selector + "#ButtonSelected.Background");
            commandBuilder.set(selector + "#ButtonSelected.TooltipText", memory.getTooltipText());
            return;
        }
        commandBuilder.set(selector + "#ButtonSelected.Visible", false);
        commandBuilder.set(selector + "#ButtonNotSelected.Visible", true);
        commandBuilder.setNull(selector + "#ButtonNotSelected.Background");
        commandBuilder.set(selector + "#ButtonNotSelected.TooltipText", memory.getTooltipText());
    }
    
    private static void updateMemoryDetailsPanel(@Nonnull final UICommandBuilder commandBuilder, @Nonnull final Memory memory) {
        commandBuilder.set("#MemoryName.Text", Message.translation(memory.getTitle()));
        commandBuilder.set("#MemoryTimeLocation.Text", "");
        if (memory instanceof final NPCMemory npcMemory) {
            final Message locationNameKey = npcMemory.getLocationMessage();
            final long capturedTimestamp = npcMemory.getCapturedTimestamp();
            final String timeString = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(Locale.getDefault()).format(Instant.ofEpochMilli(capturedTimestamp).atZone(ZoneOffset.UTC));
            final Message memoryLocationTimeText = Message.translation("server.memories.general.foundIn").param("location", locationNameKey).param("time", timeString);
            commandBuilder.set("#MemoryTimeLocation.TextSpans", memoryLocationTimeText);
        }
        final String iconPath = memory.getIconPath();
        if (iconPath != null && !iconPath.isEmpty()) {
            commandBuilder.set("#MemoryIcon.AssetPath", iconPath);
            return;
        }
        commandBuilder.setNull("#MemoryIcon.AssetPath");
    }
    
    public static class PageEventData
    {
        public static final String KEY_ACTION = "Action";
        public static final String KEY_CATEGORY = "Category";
        public static final String KEY_MEMORY_ID = "MemoryId";
        public static final BuilderCodec<PageEventData> CODEC;
        public PageAction action;
        public String category;
        public String memoryId;
        
        static {
            // 
            // This method could not be decompiled.
            // 
            // Original Bytecode:
            // 
            //     2: invokedynamic   BootstrapMethod #0, get:()Ljava/util/function/Supplier;
            //     7: invokestatic    com/hypixel/hytale/codec/builder/BuilderCodec.builder:(Ljava/lang/Class;Ljava/util/function/Supplier;)Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    10: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    13: dup            
            //    14: ldc             "Action"
            //    16: getstatic       com/hypixel/hytale/builtin/adventure/memories/page/MemoriesPage$PageAction.CODEC:Lcom/hypixel/hytale/codec/Codec;
            //    19: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    22: invokedynamic   BootstrapMethod #1, accept:()Ljava/util/function/BiConsumer;
            //    27: invokedynamic   BootstrapMethod #2, apply:()Ljava/util/function/Function;
            //    32: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
            //    35: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //    38: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    41: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    44: dup            
            //    45: ldc             "Category"
            //    47: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    50: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    53: invokedynamic   BootstrapMethod #3, accept:()Ljava/util/function/BiConsumer;
            //    58: invokedynamic   BootstrapMethod #4, apply:()Ljava/util/function/Function;
            //    63: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
            //    66: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //    69: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //    72: new             Lcom/hypixel/hytale/codec/KeyedCodec;
            //    75: dup            
            //    76: ldc             "MemoryId"
            //    78: getstatic       com/hypixel/hytale/codec/Codec.STRING:Lcom/hypixel/hytale/codec/codecs/simple/StringCodec;
            //    81: invokespecial   com/hypixel/hytale/codec/KeyedCodec.<init>:(Ljava/lang/String;Lcom/hypixel/hytale/codec/Codec;)V
            //    84: invokedynamic   BootstrapMethod #5, accept:()Ljava/util/function/BiConsumer;
            //    89: invokedynamic   BootstrapMethod #6, apply:()Ljava/util/function/Function;
            //    94: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.append:(Lcom/hypixel/hytale/codec/KeyedCodec;Ljava/util/function/BiConsumer;Ljava/util/function/Function;)Lcom/hypixel/hytale/codec/builder/BuilderField$FieldBuilder;
            //    97: invokevirtual   com/hypixel/hytale/codec/builder/BuilderField$FieldBuilder.add:()Lcom/hypixel/hytale/codec/builder/BuilderCodec$BuilderBase;
            //   100: checkcast       Lcom/hypixel/hytale/codec/builder/BuilderCodec$Builder;
            //   103: invokevirtual   com/hypixel/hytale/codec/builder/BuilderCodec$Builder.build:()Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //   106: putstatic       com/hypixel/hytale/builtin/adventure/memories/page/MemoriesPage$PageEventData.CODEC:Lcom/hypixel/hytale/codec/builder/BuilderCodec;
            //   109: return         
            // 
            // The error that occurred was:
            // 
            // java.lang.UnsupportedOperationException: The requested operation is not supported.
            //     at com.strobel.util.ContractUtils.unsupported(ContractUtils.java:27)
            //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:284)
            //     at com.strobel.assembler.metadata.TypeReference.getRawType(TypeReference.java:279)
            //     at com.strobel.assembler.metadata.TypeReference.makeGenericType(TypeReference.java:154)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:225)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:211)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitParameterizedType(TypeSubstitutionVisitor.java:25)
            //     at com.strobel.assembler.metadata.ParameterizedType.accept(ParameterizedType.java:103)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visit(TypeSubstitutionVisitor.java:40)
            //     at com.strobel.assembler.metadata.TypeSubstitutionVisitor.visitMethod(TypeSubstitutionVisitor.java:314)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2611)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1510)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:790)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferCall(TypeAnalysis.java:2689)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1040)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:782)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:778)
            //     at com.strobel.decompiler.ast.TypeAnalysis.doInferTypeForExpression(TypeAnalysis.java:1083)
            //     at com.strobel.decompiler.ast.TypeAnalysis.inferTypeForExpression(TypeAnalysis.java:815)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:684)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:667)
            //     at com.strobel.decompiler.ast.TypeAnalysis.runInference(TypeAnalysis.java:373)
            //     at com.strobel.decompiler.ast.TypeAnalysis.run(TypeAnalysis.java:95)
            //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:344)
            //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:42)
            //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:206)
            //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:93)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:868)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:761)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:638)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:662)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:605)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:195)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:162)
            //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:137)
            //     at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
            //     at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
            //     at com.strobel.decompiler.DecompilerDriver.decompileType(DecompilerDriver.java:333)
            //     at com.strobel.decompiler.DecompilerDriver.decompileJar(DecompilerDriver.java:254)
            //     at com.strobel.decompiler.DecompilerDriver.main(DecompilerDriver.java:129)
            // 
            throw new IllegalStateException("An error occurred while decompiling this method.");
        }
    }
    
    public enum PageAction
    {
        Record, 
        ViewCategory, 
        Back, 
        MemoriesInfo, 
        SelectMemory;
        
        public static final Codec<PageAction> CODEC;
        
        static {
            CODEC = new EnumCodec<PageAction>(PageAction.class);
        }
    }
}
