package net.md_5.specialsource;

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

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class ReflectionRemapper {

    private JarMapping jarMapping;

    public ReflectionRemapper(JarMapping jarMapping) {
        this.jarMapping = jarMapping;
    }

    @SuppressWarnings("unchecked")
    public byte[] remapClassFile(InputStream is) throws IOException {
        ClassReader cr = new ClassReader(is);
        ClassNode classNode = new ClassNode();
        ClassWriter cw = new ClassWriter(0);

        cr.accept(classNode, ClassReader.SKIP_DEBUG);

        for (MethodNode methodNode : (List<MethodNode>) classNode.methods) {
            AbstractInsnNode insn = methodNode.instructions.getFirst();
            while (insn != null) {
                if (insn.getOpcode() == Opcodes.INVOKEVIRTUAL) {
                    remapGetDeclaredField(insn);
                }

                insn = insn.getNext();
            }
        }

        classNode.accept(cw);

        return cw.toByteArray();
    }

    private void remapGetDeclaredField(AbstractInsnNode insn) {
        MethodInsnNode mi = (MethodInsnNode) insn;

        System.out.println("methodnode "+mi.owner+" "+mi.name+" "+mi.desc);
        if (!mi.owner.equals("java/lang/Class") || !mi.name.equals("getDeclaredField") || !mi.desc.equals("(Ljava/lang/String;)Ljava/lang/reflect/Field;")) {
            return;
        }

        System.out.println("found getDeclaredField!");

        if (insn.getPrevious() == null || insn.getPrevious().getOpcode() != Opcodes.LDC) {
            System.out.println("- not constant field; skipping");
            return;
        }
        LdcInsnNode ldcField = (LdcInsnNode) insn.getPrevious();
        System.out.println("field constant = "+ldcField.cst);
        if (!(ldcField.cst instanceof String)) {
            System.out.println("- not field string; skipping");
            return;
        }
        String fieldName = (String) ldcField.cst;

        if (ldcField.getPrevious() == null || ldcField.getPrevious().getOpcode() != Opcodes.LDC) {
            System.out.println("- not constant class; skipping");
            return;
        }
        LdcInsnNode ldcClass = (LdcInsnNode) ldcField.getPrevious();
        if (!(ldcClass.cst instanceof Type)) {
            System.out.println("- not class type; skipping");
            return;
        }
        System.out.println("class = "+ldcClass.cst);
        String className = ((Type) ldcClass.cst).getInternalName();

        System.out.println("Remapping "+className+"/"+fieldName);

        String newName = jarMapping.tryClimb(jarMapping.fields, NodeType.FIELD, className, fieldName);
        if (newName != null) {
            // Change the string literal to the correct name
            ldcField.cst = newName;
            //ldcClass.cst = className; // not remapped here - taken care of by JarRemapper
            System.out.println(" -> to "+newName);
        }
    }
}

@@ -350,16 +350,50 @@
 Mapping;
+%0A    public boolean debug = false;
 %0A%0A    pu
@@ -1357,84 +1357,8 @@
 n;%0A%0A
-        System.out.println(%22methodnode %22+mi.owner+%22 %22+mi.name+%22 %22+mi.desc);%0A
     
@@ -1550,36 +1550,40 @@
         
-System.out.println(%22
+log(%22ReflectionRemapper 
 found ge
@@ -1705,34 +1705,19 @@
         
-System.out.println
+log
 (%22- not 
@@ -1843,70 +1843,8 @@
 ();%0A
-        System.out.println(%22field constant = %22+ldcField.cst);%0A
     
@@ -1900,34 +1900,19 @@
         
-System.out.println
+log
 (%22- not 
@@ -1925,33 +1925,50 @@
 string; skipping
-%22
+: %22 + ldcField.cst
 );%0A            r
@@ -2146,34 +2146,19 @@
         
-System.out.println
+log
 (%22- not 
@@ -2173,33 +2173,56 @@
  class; skipping
-%22
+: field=%22 + ldcField.cst
 );%0A            r
@@ -2366,34 +2366,19 @@
         
-System.out.println
+log
 (%22- not 
@@ -2401,94 +2401,92 @@
 ping
-%22);%0A            return;%0A        %7D%0A        System.out.println(%22class = %22+ldcClass.cst);
+: field=%22 + ldcClass.cst + %22, class=%22 + ldcClass.cst);%0A            return;%0A        %7D
 %0A   
@@ -2555,75 +2555,8 @@
 );%0A%0A
-        System.out.println(%22Remapping %22+className+%22/%22+fieldName);%0A%0A
     
@@ -2650,24 +2650,95 @@
 fieldName);%0A
+        log(%22Remapping %22+className+%22/%22+fieldName + %22 -%3E %22 + newName);%0A%0A
         if (
@@ -2957,47 +2957,140 @@
     
-    System.out.println(%22 -%3E to %22+newNam
+%7D%0A    %7D%0A%0A    private void log(String message) %7B%0A        if (debug) %7B%0A            System.out.println(%22%5BReflectionRemapper%5D %22 + messag
 e);%0A

Add debug option to ReflectionRemapper