package shadersmod.transform;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.Remapper;

import shadersmod.common.SMCLog;
import shadersmod.common.SMCVersion;

public class SMCClassTransformer implements IClassTransformer {

	Names names;
	/** map of class transformer */	
	protected Map<String,IClassTransformer> ctMap;
	IClassTransformer modTransformer;

	public void put(Names.Clas clas, IClassTransformer ct)
	{
		ctMap.put(clas.clasName.replace('/', '.'), ct);
	}
	
	// constructor
	public SMCClassTransformer()
	{
		SMCLog.info("ShadersMod %s",SMCVersion.versionString);
		names = new Names();
		SMCConfig.getNamer().setNames();
		ctMap = new HashMap();
		// generic
		put(Names.minecraft_       , new STMinecraft());
		put(Names.guiOptions_      , new STGuiOptions());
		put(Names.openGlHelper_    , new STOpenGlHelper());
		// texture
		put(Names.iTextureObject_  , new STTextureObject());
		put(Names.abstractTexture_ , new STTextureAbstract());
		put(Names.simpleTexture_   , new STTextureSimple());
		put(Names.layeredTexture_  , new STTextureLayered());
		put(Names.dynamicTexture_  , new STTextureDynamic());
		put(Names.textureAtlasSpri_, new STTextureAtlasSprite());
		put(Names.textureMap_      , new STTextureMap());
		put(Names.textureDownload_ , new STTextureDownload());
		put(Names.textureManager_  , new STTextureManager());
		// vertex
		put(Names.vertexFormat_    , new STVertexFormat());
		put(Names.defVertexFormat_ , new STDefVertexFormat());
		// vertex buffer
		put(Names.vertexBuffer_    , new STVertexBuffer());
		put(Names.vertexBufferDrawer_ , new STVertexBufferDrawer());
		put(Names.vboRenderList_   , new STVboRenderList());
		// render world
		put(Names.renderGlobal_    , new STRenderGlobal());
		put(Names.entityRenderer_  , new STEntityRenderer());
//		put(Names.block_           , new SMCCTBlock()); // getAoLight ?
//		put(Names.itemBlock_       , new SMCCTItemBlock()); // not needed. use getBlock()
		// block model
		put(Names.bakedQuadRetextured_, new STBakedQuadRetextured());
		put(Names.faceBakery_      , new STFaceBakery());
		// render block
		put(Names.blockModelRenderer_, new STBlockModelRenderer());
		put(Names.blockRendererDispatcher_, new STBlockRendererDispatcher());
		put(Names.chunkRenderDispatcher_, new STChunkRenderDispatcher());
		put(Names.regionRenderCacheBuilder_, new STRegionRenderCacheBuilder());
		//put(Names.renderChunk_     , new SMCCTRenderChunk());
		// render block entity
		put(Names.renderItemFrame_ , new STRenderItemFrame());
		put(Names.tileEntityBeaconRenderer_   , new STTileEntityBeaconRenderer());
		// render item
//		put(Names.itemRenderer_    , new SMCCTItemRenderer());
		// entity model
		put(Names.texturedQuad_    , new STTexturedQuad());
		put(Names.modelBox_        , new STModelBox());
		put(Names.modelRenderer_   , new STModelRenderer());
		// render entity
		put(Names.render_          , new STRender()); // skip default shadow
		put(Names.renderManager_   , new STRenderManager());
//		put(Names.renderLiving_ , new SMCCTRendererLivingEntity()); // red when hurt
//		put(Names.layerDragonEyes_ , new SMCCTSpiderEyes());
//		put(Names.layerEndermanEyes_, new SMCCTSpiderEyes());
//		put(Names.layerSpiderEyes_ , new SMCCTSpiderEyes());
//		put(Names.layerArmorBase_  , new SMCCTLayerArmorBase()); // enchanted glint
		// mod
//		put(Names.ofConnectedTextures_, new SMCCTConnectedTextures()); // OptiFine
//		put(Names.forgeHooksClient_, new SMCCTForgeHooksClients()); // Forge
//		put(Names.forgeAttributes_ , new SMCCTForgeAttributes()); // Forge
//		ctMap.put("mrtjp.projectred.illumination.RenderHalo$", new SMCCTPrjRedIlluRenderHalo()); //1.7.2
//		ctMap.put("mrtjp.projectred.core.RenderHalo$", new SMCCTPrjRedIlluRenderHalo()); //1.7.10
//		ctMap.put("net.smart.render.ModelRotationRenderer", new SMCCTSmartMoveModelRotationRenderer());
		modTransformer = new DummyToAccessor();
	}

	@Override
	public byte[] transform(String name, String transformedName, byte[] byteCode) 
	{
		byte[] bytecode = byteCode;
		//SMCLog.fine("transform ? %s %s", par1, par2);
		String name1 = SMCConfig.obfName? name :transformedName;
		IClassTransformer ct = ctMap.get(name1);
		if (ct == null && name1.startsWith("shadersmod.client.")) {
			ct = modTransformer;
		}
		if (ct != null)
		{
			//SMCLog.fine("transform %s %s", name, transformedName);
			bytecode = ct.transform(name, transformedName, bytecode);
			int len1 = byteCode.length; //arg2!=null?arg2.length:0;
			int len2 = bytecode.length; //bytecode!=null?bytecode.length:0;
			//SMCLog.fine(" %d (%+d)", len2, len2-len1);
		}
		return bytecode;
	}

}