package com.bitnix.dirtcryptostore.util;

import com.bitnix.dirtcryptostore.DirtCryptoStorePlugin;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.map.*;

import java.awt.image.BufferedImage;
import java.util.List;

public final class QrMapUtil {

    private QrMapUtil() {
    }

    public static ItemStack createQrMapItem(DirtCryptoStorePlugin plugin,
                                            org.bukkit.entity.Player player,
                                            String content,
                                            String displayName,
                                            List<String> lore,
                                            String fallbackMaterialName) {
        try {
            World world = player.getWorld();
            MapView mapView = Bukkit.createMap(world);
            mapView.getRenderers().clear();
            mapView.setTrackingPosition(false);
            mapView.setUnlimitedTracking(false);
            mapView.setScale(MapView.Scale.CLOSE);

            BufferedImage image = generateQr(content, 128, 128);
            mapView.addRenderer(new ImageRenderer(image));

            ItemStack mapItem = new ItemStack(Material.FILLED_MAP);
            MapMeta meta = (MapMeta) mapItem.getItemMeta();
            if (meta != null) {
                meta.setDisplayName(displayName);
                meta.setLore(lore);
                meta.setMapView(mapView);
                mapItem.setItemMeta(meta);
            }

            return mapItem;
        } catch (Exception ex) {
            if (plugin.getConfig().getBoolean("settings.debug", false)) {
                plugin.getLogger().warning("Failed to generate QR map: " + ex.getMessage());
            }

            Material fallback = Material.matchMaterial(fallbackMaterialName);
            if (fallback == null) {
                fallback = Material.PAPER;
            }

            ItemStack item = new ItemStack(fallback);
            org.bukkit.inventory.meta.ItemMeta meta = item.getItemMeta();
            if (meta != null) {
                meta.setDisplayName(displayName);
                meta.setLore(lore);
                item.setItemMeta(meta);
            }
            return item;
        }
    }

    private static BufferedImage generateQr(String content, int width, int height) throws Exception {
        BitMatrix matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) ? 0x000000 : 0xFFFFFF);
            }
        }

        return image;
    }

    private static final class ImageRenderer extends MapRenderer {

        private final BufferedImage image;
        private boolean rendered = false;

        private ImageRenderer(BufferedImage image) {
            super(true);
            this.image = image;
        }

        @Override
        public void render(MapView mapView, MapCanvas mapCanvas, org.bukkit.entity.Player player) {
            if (rendered) {
                return;
            }

            mapCanvas.drawImage(0, 0, image);
            rendered = true;
        }
    }
}
