package com.zivilon.cinder_loe.coremod;

import net.minecraft.launchwrapper.IClassTransformer;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;

import java.util.Iterator;

public class LOTRMaterialTransformer implements IClassTransformer {
    @Override
    public byte[] transform(String name, String transformedName, byte[] classBytes) {
        if (transformedName.equals("lotr.common.item.LOTRMaterial")) {
            System.out.println("[CinderLoE] Transforming LOTRMaterial...");

            ClassReader reader = new ClassReader(classBytes);
            ClassNode classNode = new ClassNode();
            reader.accept(classNode, 0);


            modifyMaterial("ANGMAR", 480, 0.6F, classNode); //Original Durability = 350 | Add 162 | 1/4
            modifyMaterial("URUK", 662, 0.7F, classNode); //Original Durability = 550 | Add 112 | 1/4
            modifyMaterial("BLACK_URUK", 774, 0.7F, classNode); //Original Durability = 550 | Add 112 | 2/4
            modifyMaterial("HALF_TROLL", 475, 0.6F, classNode); //Original Durability = 300 | Add 175 | 1/4

            // Good Humans
            modifyMaterial("DALE", 475, 0.6F, classNode); //Original Durability = 300 | Add 175 | 1/4
            modifyMaterial("GONDOR", 725, 0.6F, classNode); //Original Durability = 450 | Add 137 | 2/4
            modifyMaterial("DORWINION_ELF", 875, 0.6F, classNode); //Original Durability = 500 | Add 125 | 2/4
            modifyMaterial("ROHAN", 300, 0.6F, classNode); //Original Durability = 300 | Add 175 | 0/4
            modifyMaterial("TAUREDAIN", 300, 0.6F, classNode); //Original Durability = 300 | Add 175 | 0/4
            modifyMaterial("DORWINION", 400, 0.6F, classNode); //Original Durability = 400 | Add 150 | 0/4
            modifyMaterial("LOSSARNACH", 300, 0.6F, classNode); //Original Durability = 300 | Add 175 | 0/4
            modifyMaterial("LAMEDON", 300, 0.6F, classNode); //Original Durability = 300 | Add 175 | 0/4


            // Evil Humans
            modifyMaterial("RHUN_GOLD", 558, 0.6F, classNode); //Original Durability = 450 | Add 137 | 1/4
            modifyMaterial("RHUN", 400, 0.6F, classNode); //Original Durability = 400 | Add 150 | 0/4
            modifyMaterial("DUNLENDING", 437, 0.6F, classNode); //Original Durability = 250 | Add 187 | 1/4
            modifyMaterial("NEAR_HARAD", 650, 0.6F, classNode); //Original Durability = 300 | Add 175 | 2/4
            modifyMaterial("HARNEDOR", 250, 0.6F, classNode); //Original Durability = 250 | Add 187 | 0/4
            modifyMaterial("CORSAIR", 300, 0.6F, classNode); //Original Durability = 300 | Add 175 | 0/4
            modifyMaterial("GULF_HARAD", 350, 0.6F, classNode); //Original Durability = 350 | Add 162 | 0/4
            modifyMaterial("UMBAR", 450, 0.6F, classNode); //Original Durability = 450 | Add 137 | 0/4
            modifyMaterial("MOREDAIN", 250, 0.6F, classNode); //Original Durability = 250 | Add 187 | 0/4

            //Elves
            modifyMaterial("WOOD_ELVEN", 1000, 0.6F, classNode); //Original Durability = 500 | Add 125 | 4/4

            // Custom
            modifyMaterial("UTUMNO", 1500, 0.7F, classNode); //Original Durability = 250 | Add 187 | 0/4

            addMaterial("RED_DWARF", classNode);
            addMaterial("WIZARD", classNode);
            addMaterial("LIMWAITH_BONE", classNode);
            addMaterial("BONEMOLD", classNode);
            addMaterial("LIMWAITH_WOOD", classNode);
            addMaterial("EVENT", classNode);
            addMaterial("BREE", classNode);
            addMaterial("BATTLENUN", classNode);
            addMaterial("ASH", classNode);
            addMaterial("RHUDAUR", classNode);
            addMaterial("SERPENT", classNode);
            addMaterial("USURPER", classNode);
            addMaterial("WARLORD",classNode);
            addMaterial("JADE",classNode);

            // Protection Conversion

            // Convert your ClassNode back to byte array with ClassWriter
            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
            classNode.accept(writer);

            byte[] transformedBytes = writer.toByteArray();
            return transformedBytes;
        }
        return classBytes;
    }

    public void addMaterial(String fieldName, ClassNode classNode) {
        FieldNode field = new FieldNode(
            Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,
            fieldName,
            "Llotr/common/item/LOTRMaterial;", // Adjust the descriptor based on the actual package name
            null,
            null
        );
        classNode.fields.add(field);
    }

    public void modifyMaterial(String fieldName, int durability, float protection, ClassNode classNode) {
        MethodNode clinit = null;
        boolean foundField = false;
        boolean durabilityModified = false;
        boolean protectionModified = false;

        // First, find the <clinit> method
        for (MethodNode method : classNode.methods) {
            if (method.name.equals("<clinit>")) {
                clinit = method;
                break;
            }
        }

        if (clinit == null) {
            return;
        }


        Iterator<AbstractInsnNode> iter = clinit.instructions.iterator();
        while (iter.hasNext()) {
            AbstractInsnNode insn = iter.next();

            if (insn instanceof LdcInsnNode && ((LdcInsnNode) insn).cst.equals(fieldName)) {
                foundField = true;
            }
            if (foundField && insn instanceof MethodInsnNode && ((MethodInsnNode) insn).name.equals("setProtection")) {
                AbstractInsnNode protectionInsn = insn.getPrevious();

                if (protectionInsn instanceof LdcInsnNode) {
                    ((LdcInsnNode) protectionInsn).cst = protection;
                    System.out.println("[CinderLoE] Updated protection for " + fieldName + " to " + protection);
                    return;
                }
            }

            if (foundField && !durabilityModified && insn instanceof MethodInsnNode && ((MethodInsnNode) insn).name.equals("setUses")) {
                AbstractInsnNode durabilityInsn = insn.getPrevious();

                if (durabilityInsn instanceof IntInsnNode) {
                    ((IntInsnNode) durabilityInsn).operand = durability;
                    System.out.println("[CinderLoE] Updated durability for " + fieldName + " to " + durability);
                    durabilityModified = true;
                }
            }

            if (foundField && !protectionModified && insn instanceof MethodInsnNode && ((MethodInsnNode) insn).name.equals("setProtection")) {
                AbstractInsnNode protectionInsn = insn.getPrevious();

                if (protectionInsn instanceof LdcInsnNode) {
                    ((LdcInsnNode) protectionInsn).cst = protection;
                    System.out.println("[CinderLoE] Updated protection for " + fieldName + " to " + protection);
                    protectionModified = true;
                }
            }

            if (durabilityModified && protectionModified) {
                return;
            }
        }

        if (!foundField) {
            System.out.println("[CinderLoE] Field '" + fieldName + "' not found in <clinit>.");
        }
    }
}
