package com.wildex999.patcher;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import com.wildex999.tickdynamic.listinject.EntityObject;

import net.minecraft.launchwrapper.IClassTransformer;

//Inject EntityObject as a base for both Entity and TileEntity for further use

public class EntityInjector implements IClassTransformer {

	@Override
	public byte[] transform(String name, String transformedName,
			byte[] basicClass) {
		
		if(!transformedName.equals("net.minecraft.entity.Entity") && !transformedName.equals("net.minecraft.tileentity.TileEntity"))
			return basicClass;
		System.out.println("Entity Inject: " + transformedName);
		
		ClassReader cr = new ClassReader(basicClass);
		ClassWriter cw = new ClassWriter(0);
		ClassInjectorVisitor iv = new ClassInjectorVisitor(Opcodes.ASM4, cw);
		cr.accept(iv, ClassReader.EXPAND_FRAMES);
		
		
		return cw.toByteArray();
	}
	
	//Inject super class
	private class ClassInjectorVisitor extends ClassVisitor {

		boolean done = false;
		
		public ClassInjectorVisitor(int api, ClassVisitor cv) {
			super(api, cv);
		}

		@Override
		public void visit(int version, int access, String name,
				String signature, String superName, String[] interfaces) {
			if(!superName.equals("java/lang/Object"))
			{
				System.err.println("WARNING: " + name + " already has a super class which will be overwritten: " + superName 
						+ "\nThis means that some other mod might no longer work properly!");
			}
			super.visit(version, access+Opcodes.ACC_SUPER, name, signature, EntityObject.class.getName().replace('.', '/'), interfaces);
		}
		
		@Override
		public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
			if(!done && name.equals("<init>"))
			{
				done = true;
				return new MedthodInjectorVisitor(super.api, super.visitMethod(access, name, desc, signature, exceptions));
			}
			else
				return super.visitMethod(access, name, desc, signature, exceptions);
		}
		
	}
	
	//Replace constructor init to use super
	private class MedthodInjectorVisitor extends MethodVisitor {

		boolean gotInit = false;
		
		public MedthodInjectorVisitor(int api, MethodVisitor mv) {
			super(api, mv);
		}
		
		@Override
		public void visitMethodInsn(int opcode, String owner, String name,
				String desc, boolean itf) {
			if(!gotInit && opcode == Opcodes.INVOKESPECIAL)
			{
				super.visitMethodInsn(opcode, EntityObject.class.getName().replace('.', '/'), name, desc, itf);
				gotInit = true;
			}
			else
				super.visitMethodInsn(opcode, owner, name, desc, itf);
		}
		
	}
}