package shadersmod.transform;

import static org.objectweb.asm.Opcodes.*;

import java.util.HashMap;
import java.util.Map;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodInsnNode;

public class DummyData {
	static Map<String,InsnList> mapDummyToInsnList = new HashMap<String,InsnList>();
	
	static void addFieldAccessor(String aclas, String aname, Names.Fiel target) {
		String accessorName;
		String accessorDesc;
		String dummyName;
		InsnList insnList;
		// get
		dummyName    = "get_"+aclas+"_"+aname;
		accessorName = "get_"+aname;
		accessorDesc = "("+target.clasRef.desc+")"+target.desc;
		insnList = new InsnList();
		insnList.add(new MethodInsnNode(INVOKESTATIC,target.clasName,accessorName,accessorDesc));
		mapDummyToInsnList.put(dummyName, insnList);
		// put
		dummyName    = "put_"+aclas+"_"+aname;
		accessorName = "put_"+aname;
		accessorDesc = "("+target.clasRef.desc+target.desc+")V";
		insnList = new InsnList();
		insnList.add(new MethodInsnNode(INVOKESTATIC,target.clasName,accessorName,accessorDesc));
		mapDummyToInsnList.put(dummyName, insnList);
	}
	
	static void addField(String aclas, String aname, Names.Fiel target) {
		String dummyName;
		InsnList insnList;
		// get
		dummyName    = "get_"+aclas+"_"+aname;
		insnList = new InsnList();
		insnList.add(new FieldInsnNode(GETFIELD,target.clasName,target.name,target.desc));
		mapDummyToInsnList.put(dummyName, insnList);
		// put
		dummyName    = "put_"+aclas+"_"+aname;
		insnList = new InsnList();
		insnList.add(new FieldInsnNode(PUTFIELD,target.clasName,target.name,target.desc));
		mapDummyToInsnList.put(dummyName, insnList);
	}
	
	static void addMethodSpecialAccessor(String aclas, String aname, Names.Meth target) {
		String accessorName;
		String accessorDesc;
		String dummyName;
		InsnList insnList;
		dummyName    = "invoke_"+aclas+"_"+aname;
		accessorName = "invoke_"+aname;
		accessorDesc = "("+target.clasRef.desc+target.desc.substring(1);
		insnList = new InsnList();
		insnList.add(new MethodInsnNode(INVOKESTATIC,target.clasName,accessorName,accessorDesc));
		mapDummyToInsnList.put(dummyName, insnList);
	}
	static void addMethodStatic(String aclas, String aname, Names.Meth target) {
		String dummyName;
		InsnList insnList;
		dummyName    = "invoke_"+aclas+"_"+aname;
		insnList = new InsnList();
		insnList.add(new MethodInsnNode(INVOKESTATIC,target.clasName,target.name,target.desc));
		mapDummyToInsnList.put(dummyName, insnList);
	}
	static void addMethodVirtual(String aclas, String aname, Names.Meth target) {
		String dummyName;
		InsnList insnList;
		dummyName    = "invoke_"+aclas+"_"+aname;
		insnList = new InsnList();
		insnList.add(new MethodInsnNode(INVOKEVIRTUAL,target.clasName,target.name,target.desc));
		mapDummyToInsnList.put(dummyName, insnList);
	}
	static void addMethodInterface(String aclas, String aname, Names.Meth target) {
		String dummyName;
		InsnList insnList;
		dummyName    = "invoke_"+aclas+"_"+aname;
		insnList = new InsnList();
		insnList.add(new MethodInsnNode(INVOKEINTERFACE,target.clasName,target.name,target.desc));
		mapDummyToInsnList.put(dummyName, insnList);
	}
	static {
		// direct
		addField("vertexBuffer","sVertexBuffer",Names.vertexBuffer_sVertexBuffer);
		addField("vertexFormat","tangentElementOffset",Names.vertexFormat_tangentElementOffset);
		addField("vertexFormat","entityElementOffset",Names.vertexFormat_entityElementOffset);
		addField("vertexFormat","miduvElementOffset",Names.vertexFormat_miduvElementOffset);
		addField("abstractTexture","multiTex",Names.abstractTexture_multiTex);
		addField("textureMap","atlasWidth" ,Names.textureMap_atlasWidth);
		addField("textureMap","atlasHeight",Names.textureMap_atlasHeight);
		addMethodVirtual("modelRenderer","resetDisplayList",Names.modelRenderer_resetDisplayList);
		addMethodInterface("iTextureObject","getMultiTexID",Names.iTextureObject_getMultiTexID);
		addMethodStatic("forgeHooksClient","setRenderPass",Names.forgeHooksClient_setRenderPass);
		// use accessor
//		addFieldAccessor("itemBLock"      ,"block"          ,Names.itemBlock_block              );
		addFieldAccessor("textureMap"     ,"basePath"       ,Names.textureMap_basePath          );
		addFieldAccessor("entityRenderer" ,"frameCount"     ,Names.entityRenderer_frameCount    );
		addFieldAccessor("vertexBuffer"   ,"rawIntBuffer"   ,Names.vertexBuffer_rawIntBuffer    );
		addFieldAccessor("vertexBuffer"   ,"rawFloatBuffer" ,Names.vertexBuffer_rawFloatBuffer  );
		addFieldAccessor("vertexBuffer"   ,"vertexCount"    ,Names.vertexBuffer_vertexCount     );
//		addFieldAccessor("vertexBuffer"   ,"rawBufferIndex" ,Names.vertexBuffer_rawBufferIndex  );
		addFieldAccessor("vertexBuffer"   ,"drawMode"       ,Names.vertexBuffer_drawMode        );
		addFieldAccessor("vertexBuffer"   ,"vertexElement"  ,Names.vertexBuffer_vertexElement);
		addFieldAccessor("vertexBuffer"   ,"vertexElementIndex",Names.vertexBuffer_vertexElementIndex);
		addFieldAccessor("vertexFormat"   ,"offsets"        ,Names.vertexFormat_offsets         );
		addFieldAccessor("vertexFormat"   ,"nextOffset"     ,Names.vertexFormat_nextOffset      );
		addFieldAccessor("vertexFormat"   ,"colorElementOffset" ,Names.vertexFormat_colorElementOffset );
		addFieldAccessor("vertexFormat"   ,"uvOffsets"      ,Names.vertexFormat_uvOffsets       );
		addFieldAccessor("vertexFormat"   ,"normalElementOffset",Names.vertexFormat_normalElementOffset);
		addFieldAccessor("renderManager"  ,"entityRenderMap",Names.renderManager_entityRenderMap);
		addFieldAccessor("abstractTexture","glTextureId"    ,Names.abstractTexture_glTextureId  );
		addFieldAccessor("texturedQuad"   ,"invertNormal"   ,Names.texturedQuad_invertNormal    );
		addMethodSpecialAccessor("entityRenderer","renderHand",Names.entityRenderer_renderHand  );
		addMethodSpecialAccessor("entityRenderer","setupCameraTransform",Names.entityRenderer_setupCameraTransform);
		//addMethodSpecialAccessor("textureMap","completeResLoc",Names.textureMap_getIconResLoc   );
	}

}
