package p.studio.workspaces.assets.details.palette;

import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import p.studio.Container;
import p.studio.controls.banks.StudioDualListView;
import p.studio.utilities.i18n.I18n;
import p.studio.workspaces.assets.messages.AssetWorkspaceBankCompositionFile;

import java.util.List;
import java.util.Map;

public final class AssetDetailsPaletteOverhaulingDualListView extends StudioDualListView<AssetWorkspaceBankCompositionFile> {
    public AssetDetailsPaletteOverhaulingDualListView() {
        setLeftTitle(Container.i18n().text(I18n.ASSETS_PALETTE_OVERHAULING_AVAILABLE));
        setRightTitle(Container.i18n().text(I18n.ASSETS_PALETTE_OVERHAULING_SELECTED));
    }

    @Override
    protected String itemText(AssetWorkspaceBankCompositionFile item) {
        return "";
    }

    @Override
    protected Node itemGraphic(AssetWorkspaceBankCompositionFile item) {
        final Label hashLabel = new Label(item.displayName());
        hashLabel.getStyleClass().add("assets-details-palette-hash");
        final HBox strip = createPaletteStrip(item);
        final HBox top = new HBox(8, hashLabel, strip);
        top.getStyleClass().add("assets-details-palette-item");
        final Object invalidReason = item.metadata().get("invalidReason");
        if (!(invalidReason instanceof String reason) || reason.isBlank()) {
            return top;
        }
        final Label invalidLabel = new Label(reason);
        invalidLabel.getStyleClass().add("assets-details-palette-invalid");
        final VBox root = new VBox(4, top, invalidLabel);
        return root;
    }

    private HBox createPaletteStrip(AssetWorkspaceBankCompositionFile item) {
        final HBox strip = new HBox(0);
        strip.getStyleClass().add("assets-details-palette-strip");
        final List<Integer> colors = paletteDisplayColors(item.metadata());
        for (int index = 0; index < 15; index++) {
            final Region swatch = new Region();
            swatch.getStyleClass().add("assets-details-palette-swatch");
            swatch.setMinSize(12.0d, 18.0d);
            swatch.setPrefSize(12.0d, 18.0d);
            swatch.setMaxSize(12.0d, 18.0d);
            swatch.setStyle("-fx-background-color: " + cssColor(colorAt(colors, index)) + ";");
            strip.getChildren().add(swatch);
        }
        return strip;
    }

    @SuppressWarnings("unchecked")
    private List<Integer> paletteDisplayColors(Map<String, Object> metadata) {
        final Object paletteValue = metadata.get("palette");
        if (!(paletteValue instanceof Map<?, ?> palette)) {
            return List.of();
        }
        final Object convertedValue = palette.get("convertedRgb565");
        if (convertedValue instanceof List<?> converted) {
            return ((List<Integer>) converted).stream()
                    .map(this::rgb565ToArgb8888)
                    .toList();
        }
        return List.of();
    }

    private int colorAt(List<Integer> colors, int index) {
        if (index < 0 || index >= colors.size()) {
            return 0x00000000;
        }
        final Integer color = colors.get(index);
        return color == null ? 0x00000000 : color;
    }

    private String cssColor(int argb) {
        final int alpha = (argb >>> 24) & 0xFF;
        if (alpha == 0) {
            return "transparent";
        }
        final int red = (argb >>> 16) & 0xFF;
        final int green = (argb >>> 8) & 0xFF;
        final int blue = argb & 0xFF;
        return String.format("#%02X%02X%02X", red, green, blue);
    }

    private int rgb565ToArgb8888(Integer rgb565) {
        if (rgb565 == null) {
            return 0x00000000;
        }
        final int value = rgb565 & 0xFFFF;
        final int red = ((value >> 11) & 0x1F) * 255 / 31;
        final int green = ((value >> 5) & 0x3F) * 255 / 63;
        final int blue = (value & 0x1F) * 255 / 31;
        return 0xFF000000 | (red << 16) | (green << 8) | blue;
    }
}
