package com.agentdid127.resourcepack.library.utilities.slicing;

import com.agentdid127.resourcepack.library.utilities.FileUtil;
import com.agentdid127.resourcepack.library.utilities.ImageConverter;
import com.agentdid127.resourcepack.library.utilities.JsonUtil;
import com.agentdid127.resourcepack.library.utilities.Logger;
import com.google.gson.Gson;
import com.google.gson.JsonObject;

import java.io.IOException;
import java.nio.file.Path;

public class Slicer {
    public static void run(Gson gson, Slice slice, Path root, /* nullable */ PredicateRunnable predicateRunnable, int from, boolean has_metadata) throws IOException {
        if (predicateRunnable != null && !predicateRunnable.run(from, slice.getPredicate())) {
            return;
        }

        Path path = root.resolve(slice.getPath());
        if (!path.toFile().exists()) {
            Logger.debug("Texture '" + slice.getPath() + "' doesn't exist, ignoring...");
            return;
        }

        ImageConverter converter = new ImageConverter(slice.getWidth(), slice.getHeight(), path);

        Path imagePath = path;
        if (slice.getPathName() != null) {
            imagePath = path.resolveSibling(slice.getPathName());
        }

        for (Texture texture : slice.getTextures()) {
            Path texturePath = root.resolve(texture.getPath());
            if (texturePath.toFile().exists()) {
                // Sometimes packs include both newer and older textures but
                // since we are upgrading to a newer version, we want what was shown in the original
                // version so we delete the existing new one, so we can replace it with the
                // version used in said version.
                texturePath.toFile().delete();
            }
            FileUtil.ensureParentExists(texturePath);

            if (predicateRunnable != null && !predicateRunnable.run(from, texture.getPredicate())) {
                continue;
            }

            try {
                Box box = texture.getBox();
                converter.saveSlice(box.getX(), box.getY(), box.getWidth(), box.getHeight(), texturePath);
                if (texture.shouldRemove()) {
                    converter.fillEmpty(box.getX(), box.getY(), box.getWidth(), box.getHeight());
                }

                if (has_metadata) {
                    JsonObject metadata = texture.getMetadata();
                    if (!metadata.keySet().isEmpty() && !metadata.entrySet().isEmpty()) {
                        Path metadataPath = texturePath.resolveSibling(texturePath.getFileName() + ".mcmeta");
                        JsonUtil.writeJson(gson, metadataPath, metadata);
                    }
                }
            } catch (Exception exception) {
                Logger.log("Failed to slice texture '" + texture.getPath() + "' (error='" + exception.getLocalizedMessage() + "')");
                Logger.log("  - box: (x=" + texture.getBox().getX() + ", y=" + texture.getBox().getY() + ", width=" + texture.getBox().getWidth() + ", height=" + texture.getBox().getHeight() + ")");
            }
        }

        if (!path.toFile().delete()) {
            Logger.debug("Failed to remove '" + path.getFileName() + "' whilst slicing.");
        }

        if (!slice.shouldDelete()) {
            converter.store(imagePath);
        }
    }
}
