/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.bausystem.features.util;

import de.steamwar.bausystem.BauSystem;
import de.steamwar.inventory.SWItem;
import de.steamwar.inventory.SWListInv;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.PistonMoveReaction;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.entity.Player;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class MaterialLazyInit {

    static List<MaterialData> materialData = new ArrayList<>();

    static {
        for (Material value : Material.values()) {
            if (!value.isBlock()) {
                continue;
            }
            if (value.isLegacy()) {
                continue;
            }
            materialData.add(new MaterialData(value));
        }
    }

    static class MaterialData {
        private Material material;
        private Material originalMaterial;

        private String name;
        private double blastResistance;
        private double hardness;
        private boolean transparent;
        private boolean solid;
        private boolean gravity;
        private boolean occluding;
        private boolean interacteable;
        private boolean flammable;
        private boolean burnable;
        private boolean waterloggable;
        private boolean unmoveable;

        public MaterialData(Material material) {
            this.originalMaterial = material;

            name = material.name();
            blastResistance = material.getBlastResistance();
            hardness = material.getHardness();
            transparent = material.isTransparent();
            solid = material.isSolid();
            gravity = material.hasGravity();
            occluding = material.isOccluding();
            interacteable = material.isInteractable();
            flammable = material.isFlammable();
            burnable = material.isBurnable();
            BlockData blockData = material.createBlockData();
            waterloggable = blockData instanceof Waterlogged;
            if (material.isBlock()) {
                Block block = Bukkit.getWorlds().get(0).getBlockAt(0, 0, 0);
                block.setType(material);
                unmoveable = block.getPistonMoveReaction() == PistonMoveReaction.BLOCK || block.getPistonMoveReaction() == PistonMoveReaction.IGNORE || block.getState() instanceof TileState;
            }

            if (material.isItem() && material != Material.AIR) {
                this.material = material;
            } else {
                this.material = Material.GHAST_TEAR;
            }
        }

        public SWListInv.SWListEntry<Material> toSWItem(Player p) {
            List<String> lore = new ArrayList<>();
            lore.add(BauSystem.MESSAGE.parse("MATERIAL_BLAST_RESISTANCE", p, blastResistance));
            lore.add(BauSystem.MESSAGE.parse(blastResistance > 9 ? "MATERIAL_TNT_UNBREAKABLE" : "MATERIAL_TNT_BREAKABLE", p));
            lore.add(BauSystem.MESSAGE.parse("MATERIAL_HARDNESS", p, hardness));
            if (transparent) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_TRANSPARENT", p));
            }
            if (solid) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_SOLID", p));
            }
            if (gravity) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_GRAVITY", p));
            }
            if (occluding) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_OCCLUDING", p));
            }
            if (interacteable) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_INTERACTABLE", p));
            }
            if (flammable) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_FLAMMABLE", p));
            }
            if (burnable) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_BURNABLE", p));
            }
            if (waterloggable) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_WATERLOGGABLE", p));
            }
            if (unmoveable) {
                lore.add(BauSystem.MESSAGE.parse("MATERIAL_UNMOVABLE", p));
            }
            return new SWListInv.SWListEntry<>(new SWItem(material, "§e" + name, lore, false, clickType -> {
            }), originalMaterial);
        }

        public boolean is(MaterialCommand.Search search) {
            boolean result = true;
            result &= search.transparent.test(transparent);
            result &= search.solid.test(solid);
            result &= search.gravity.test(gravity);
            result &= search.occluding.test(occluding);
            result &= search.interacteable.test(interacteable);
            result &= search.flammable.test(flammable);
            result &= search.burnable.test(burnable);
            result &= search.waterloggable.test(waterloggable);
            result &= search.unmoveable.test(unmoveable);
            if (!result) {
                return false;
            }
            if (!search.blastResistance.isEmpty()) {
                String[] strings = search.blastResistance.split(" ");
                for (String string : strings) {
                    string = string.replace(",", ".");
                    if (string.startsWith("=")) {
                        if (blastResistance != Double.parseDouble(string.substring(1))) return false;
                    } else if (string.startsWith(">=")) {
                        if (blastResistance < Double.parseDouble(string.substring(2))) return false;
                    } else if (string.startsWith("<=")) {
                        if (blastResistance > Double.parseDouble(string.substring(2)))return false;
                    } else if (string.startsWith(">")) {
                        if (blastResistance <= Double.parseDouble(string.substring(1))) return false;
                    } else if (string.startsWith("<")) {
                        if (blastResistance >= Double.parseDouble(string.substring(1))) return false;
                    } else if (string.startsWith("!")) {
                        if (blastResistance == Double.parseDouble(string.substring(1))) return false;
                    }
                }
            }
            if (search.name.isEmpty()) {
                return true;
            }
            return Pattern.compile(search.name.toLowerCase().replace(".", ".+").replace(" ", ".")).asPredicate().test(name.toLowerCase());
        }
    }
}
