package net.minecraft.client.gui.screens.packs;

import net.minecraft.ChatFormatting;
import org.apache.logging.log4j.LogManager;
import net.minecraft.client.gui.screens.ConfirmScreen;
import net.minecraft.network.chat.TextComponent;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import net.minecraft.client.gui.components.toasts.SystemToast;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.FileVisitOption;
import org.apache.commons.lang3.mutable.MutableBoolean;
import java.nio.file.Path;
import java.util.List;
import net.minecraft.client.Minecraft;
import com.mojang.blaze3d.vertex.PoseStack;
import java.util.stream.Stream;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.Util;
import net.minecraft.network.chat.CommonComponents;
import java.util.function.Function;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.client.gui.components.Button;
import java.io.File;
import net.minecraft.network.chat.Component;
import org.apache.logging.log4j.Logger;
import net.minecraft.client.gui.screens.Screen;

public abstract class PackSelectionScreen extends Screen {
    private static final Logger LOGGER;
    private static final Component DRAG_AND_DROP;
    private static final Component DIRECTORY_BUTTON_TOOLTIP;
    private final PackSelectionModel<?> model;
    private final Screen lastScreen;
    private boolean shouldCommit;
    private TransferableSelectionList availablePackList;
    private TransferableSelectionList selectedPackList;
    private final File packDir;
    private Button doneButton;
    
    public PackSelectionScreen(final Screen dqs, final TranslatableComponent ne, final Function<Runnable, PackSelectionModel<?>> function, final File file) {
        super(ne);
        this.lastScreen = dqs;
        this.model = function.apply(this::populateLists);
        this.packDir = file;
    }
    
    @Override
    public void removed() {
        if (this.shouldCommit) {
            this.shouldCommit = false;
            this.model.commit();
        }
    }
    
    @Override
    public void onClose() {
        this.shouldCommit = true;
        this.minecraft.setScreen(this.lastScreen);
    }
    
    @Override
    protected void init() {
        this.doneButton = this.<Button>addButton(new Button(this.width / 2 + 4, this.height - 48, 150, 20, CommonComponents.GUI_DONE, dni -> this.onClose()));
        this.<Button>addButton(new Button(this.width / 2 - 154, this.height - 48, 150, 20, new TranslatableComponent("pack.openFolder"), dni -> Util.getPlatform().openFile(this.packDir), (dni, dhl, integer3, integer4) -> this.renderTooltip(dhl, PackSelectionScreen.DIRECTORY_BUTTON_TOOLTIP, integer3, integer4)));
        (this.availablePackList = new TransferableSelectionList(this.minecraft, 200, this.height, new TranslatableComponent("pack.available.title"))).setLeftPos(this.width / 2 - 4 - 200);
        this.children.add(this.availablePackList);
        (this.selectedPackList = new TransferableSelectionList(this.minecraft, 200, this.height, new TranslatableComponent("pack.selected.title"))).setLeftPos(this.width / 2 + 4);
        this.children.add(this.selectedPackList);
        this.populateLists();
    }
    
    private void populateLists() {
        this.updateList(this.selectedPackList, this.model.getSelected());
        this.updateList(this.availablePackList, this.model.getUnselected());
        this.doneButton.active = !this.selectedPackList.children().isEmpty();
    }
    
    private void updateList(final TransferableSelectionList dth, final Stream<PackSelectionModel.Entry> stream) {
        dth.children().clear();
        stream.forEach(a -> dth.children().add(new TransferableSelectionList.PackEntry(this.minecraft, dth, this, a)));
    }
    
    private void reload() {
        this.model.findNewPacks();
        this.populateLists();
        this.shouldCommit = true;
    }
    
    @Override
    public void render(final PoseStack dhl, final int integer2, final int integer3, final float float4) {
        this.renderDirtBackground(0);
        this.availablePackList.render(dhl, integer2, integer3, float4);
        this.selectedPackList.render(dhl, integer2, integer3, float4);
        this.drawCenteredString(dhl, this.font, this.title, this.width / 2, 8, 16777215);
        this.drawCenteredString(dhl, this.font, PackSelectionScreen.DRAG_AND_DROP, this.width / 2, 20, 16777215);
        super.render(dhl, integer2, integer3, float4);
    }
    
    protected static void copyPacks(final Minecraft dlx, final List<Path> list, final Path path) {
        final MutableBoolean mutableBoolean4 = new MutableBoolean();
        Stream<Path> stream4;
        final MutableBoolean mutableBoolean5;
        final Throwable t2;
        final MutableBoolean mutableBoolean6;
        list.forEach(path3 -> {
            try {
                stream4 = Files.walk(path3);
                try {
                    stream4.forEach(path4 -> {
                        try {
                            Util.copyBetweenDirs(path3.getParent(), path, path4);
                        }
                        catch (IOException iOException5) {
                            PackSelectionScreen.LOGGER.warn("Failed to copy datapack file  from {} to {}", path4, path, iOException5);
                            mutableBoolean5.setTrue();
                        }
                        return;
                    });
                }
                catch (Throwable t) {
                    throw t;
                }
                finally {
                    if (stream4 != null) {
                        if (t2 != null) {
                            try {
                                stream4.close();
                            }
                            catch (Throwable exception) {
                                t2.addSuppressed(exception);
                            }
                        }
                        else {
                            stream4.close();
                        }
                    }
                }
            }
            catch (IOException iOException6) {
                PackSelectionScreen.LOGGER.warn("Failed to copy datapack file from {} to {}", path3, path);
                mutableBoolean6.setTrue();
            }
            return;
        });
        if (mutableBoolean4.isTrue()) {
            SystemToast.onPackCopyFailure(dlx, path.toString());
        }
    }
    
    @Override
    public void onFilesDrop(final List<Path> list) {
        final String string3 = list.stream().map(Path::getFileName).map(Path::toString).collect(Collectors.joining(", "));
        this.minecraft.setScreen(new ConfirmScreen(boolean2 -> {
            if (boolean2) {
                copyPacks(this.minecraft, list, this.packDir.toPath());
                this.reload();
            }
            this.minecraft.setScreen(this);
        }, new TranslatableComponent("pack.dropConfirm"), new TextComponent(string3)));
    }
    
    static {
        LOGGER = LogManager.getLogger();
        DRAG_AND_DROP = new TranslatableComponent("pack.dropInfo").withStyle(ChatFormatting.DARK_GRAY);
        DIRECTORY_BUTTON_TOOLTIP = new TranslatableComponent("pack.folderInfo");
    }
}
