package shadersmod.transform;

import java.util.Iterator;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import static org.objectweb.asm.Opcodes.*;
import static shadersmod.transform.Names.sVertexBuffer_enableCalcNormal;

import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.tree.MethodNode;

import shadersmod.client.SVertexFormat;
import shadersmod.common.SMCLog;
import net.minecraft.launchwrapper.IClassTransformer;

// for RegionRenderCacheBuilder

public class STRegionRenderCacheBuilder implements IClassTransformer {

	@Override
	public byte[] transform(String par1, String par2, byte[] par3) {
		SMCLog.fine("transforming %s %s",par1,par2);
		ClassReader cr = new ClassReader(par3);
		ClassWriter cw = new ClassWriter(cr, 0);
		CVTransform cv = new CVTransform(cw);
		cr.accept(cv,0);
		return cw.toByteArray();
	}

	private static class CVTransform extends ClassVisitor
	{
		String classname;
		boolean endFields = false;
		
		public CVTransform(ClassVisitor cv)
		{
			super(Opcodes.ASM4, cv);		
		}

		@Override
		public void visit(int version, int access, String name,
				String signature, String superName, String[] interfaces) {
			classname = name;
			//SMCLog.info(" class %s",name);
			cv.visit(version, access, name, signature, superName, interfaces);
		}

		@Override
		public MethodVisitor visitMethod(int access, String name, String desc,
				String signature, String[] exceptions) {
			if (Names.regionRenderCacheBuilder_init.equalsNameDesc(name,desc)) {
				return new MVinit(cv.visitMethod(access, name, desc, signature, exceptions));
			}
			return cv.visitMethod(access, name, desc, signature, exceptions);
		}
	}

	private static class MVinit extends MethodVisitor
	{
		public MVinit(MethodVisitor mv) {
			super(Opcodes.ASM4, mv);
		}
		
		@Override
		public void visitLdcInsn(Object cst) {
			if (cst instanceof Integer) {
				int value = ((Integer) cst).intValue();
				if (value==2097152 || value==131072 || value==262144) {
					super.visitLdcInsn(new Integer(value*SVertexFormat.vertexSizeBlock/SVertexFormat.vertexSizeBlockVanilla));
					return;
				}
			}
			super.visitLdcInsn(cst);
		}

		@Override
		public void visitInsn(int opcode) {
			if (opcode==RETURN) {
				mv.visitVarInsn(ALOAD, 0);
				mv.visitFieldInsn(GETFIELD, 
						Names.regionRenderCacheBuilder_vertexBuffers.clasName,
						Names.regionRenderCacheBuilder_vertexBuffers.name,
						Names.regionRenderCacheBuilder_vertexBuffers.desc);
				mv.visitFieldInsn(GETSTATIC, Names.blockRenderLayer_translucent.clasName, Names.blockRenderLayer_translucent.name, Names.blockRenderLayer_translucent.desc);
				mv.visitMethodInsn(INVOKEVIRTUAL, Names.blockRenderLayer_.clasName, "ordinal", "()I", false);
				mv.visitInsn(AALOAD);
				mv.visitMethodInsn(INVOKESTATIC, Names.sVertexBuffer_enableCalcNormal.clasName, Names.sVertexBuffer_enableCalcNormal.name, Names.sVertexBuffer_enableCalcNormal.desc, false);
			}
			super.visitInsn(opcode);
		}
	}
}
