package shadersmod.transform;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.commons.SimpleRemapper;

import shadersmod.transform.Names.Clas;
import shadersmod.transform.Names.Fiel;
import shadersmod.transform.Names.Meth;

public class NamerMcp extends NamerSrg {
	
	ArrayList<String> obfNames;

	@Override
	public void beginSetNames() {
		obfNames = new ArrayList();
	}
	@Override
	public void endSetNames() {
		try {
			new File("shadersmod/transform").mkdirs();
			PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream("shadersmod/transform/obfnames.txt"),StandardCharsets.UTF_8));
			for (String s : obfNames) {
				if (s != null) {
					writer.println(s);
				} else {
					System.out.println("null");
				}
			}			
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		obfNames = null;
	}
	
	public void rename()
	{
		rename("../conf/");
	}
	
	public void rename(String confPath)
	{
		Map<String,String> nameMapF;
		Map<String,String> nameMapM;
		nameMapF = loadNameMapCSV(confPath+"fields.csv");
		nameMapM = loadNameMapCSV(confPath+"methods.csv");
		
		// print srg, reobf, mcp names
		printReobfName(confPath, nameMapF, nameMapM);
		
		// rename srg to mcp
		for (Fiel f : af) {
			String s = nameMapF.get(f.name);
			if (s!= null) {
				f.name = s;
			}
		}
		for (Meth m : am) {
			String s = nameMapM.get(m.name);
			if (s!= null) {
				m.name = s;
			}
		}
	}
	
	Map loadNameMapCSV(String fileName)
	{
		Map map = new HashMap();
		BufferedReader rd = null;
		try {
	 		rd = new BufferedReader(new FileReader(fileName));
			String line;
			rd.readLine(); // skip first line;
			while ((line = rd.readLine()) != null) {
				String[] tokens = line.split(",");
				if(tokens.length>1)
				{
					map.put(tokens[0],tokens[1]);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return map;
	}

	void printReobfName(String confPath, Map<String,String> nameMapF, Map<String,String> nameMapM)
	{
		// print srg, reobf, mcp names
		Map<String,String> nameMapR;
		nameMapR = loadReobfMap(confPath+"joined.srg");
		for (Clas c : ac) {
			String reoname = nameMapR.get(c.name);
			System.out.printf("C %s %s\n",c.name,reoname);
			if (reoname==null) 
				System.err.printf("C %s %s\n",c.name,reoname);;
			obfNames.add(reoname);
		}
		for (Fiel f : af) {
			String reoname = nameMapR.get(f.clasName+"/"+f.name);
			String mcpname = nameMapF.get(f.name);
			System.out.printf("F %s %s %s %s %s\n",f.name,(reoname!=null?reoname:"####"),f.clasName,mcpname,f.desc);
			if (reoname==null) 
				System.err.printf("F %s %s %s %s %s\n",f.name,(reoname!=null?reoname:"####"),f.clasName,mcpname,f.desc);
			obfNames.add(reoname);
		}
		for (Meth m : am) {
			String reoname = nameMapR.get(m.clasName+"/"+m.name+m.desc);
			String mcpname = nameMapM.get(m.name);
			System.out.printf("M %s %s %s %s %s\n",m.name,(reoname!=null?reoname:"####"),m.clasName,mcpname,m.desc);
			if (reoname==null) 
				System.err.printf("M %s %s %s %s %s\n",m.name,(reoname!=null?reoname:"####"),m.clasName,mcpname,m.desc);
			obfNames.add(reoname);
		}
	}


	Map loadReobfMap(String fileName)
	{
		Map map = new HashMap();
		BufferedReader rd = null;
		try {
	 		rd = new BufferedReader(new FileReader(fileName));
			String line;
			while ((line = rd.readLine()) != null) {
				String[] tokens = line.split(" ");
				if(tokens.length>1)
				{
					if ("CL:".equals(tokens[0])) {
						map.put(tokens[2], tokens[1]);
					} else if ("FD:".equals(tokens[0])) {
						map.put(tokens[2], tokens[1].substring(tokens[1].lastIndexOf('/')+1));
					} else if ("MD:".equals(tokens[0])) {
						map.put(tokens[3]+tokens[4], tokens[1].substring(tokens[1].lastIndexOf('/')+1));
					}
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return map;
	}
}
