package dfixer;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;

public class FileGen {
	private int ID = 0;
	private ArrayList<Instruction> Ilist = new ArrayList<Instruction>();
	private String path;

	public FileGen(String insfilename,String path){
		if(path.endsWith("/"))
			this.path = path;
		else
			this.path = path+"/";
		File file = new File(this.path+insfilename);
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			String tmp = null;
			while((tmp = br.readLine())!=null){
				Instruction ins = new Instruction(tmp,path);
				if(ins.gettype()=='D' || ins.gettype()=='P' || ins.gettype()=='A' || ins.gettype()=='#')
					Ilist.add(ins);
			}
			br.close();
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}
	
	public void Gen() throws IOException, InterruptedException{
		int i = 0;
		int n = Ilist.size();
		while(i<n){
			Instruction tmpins = Ilist.get(i);
			if(tmpins.gettype()=='#'){
				ID++;
				i++;
				ArrayList<Instruction> inslist = new ArrayList<Instruction>();
				Instruction ins = Ilist.get(i);
				while(ins.gettype()!='#' && i<n){
					inslist.add(ins);
					i++;
					if(i<n)
						ins = Ilist.get(i);
					else 
						break;
				}
				//fixing ID deal with instruction list
				SubGen(inslist,ID);
			}
		}
	}
	
	private void SubGen(ArrayList<Instruction> inslist,int ID) throws IOException, InterruptedException{
		Collections.sort(inslist,new InsSort());
		HashMap<String,String> map = new HashMap<String,String>();
		ArrayList<String> file = new ArrayList<String>();
		int n = inslist.size();
		String id = String.valueOf(ID);
		
		for(int i=0;i<n;i++){
			Instruction ins = inslist.get(i);
			String from_filename = ins.getname();	
			String to_filename = id + from_filename;
			if(!map.containsKey(from_filename))
				map.put(from_filename, to_filename);
		}
		
		Iterator<String> it1 = map.keySet().iterator();  
		while(it1.hasNext()){
			String from_filename = (String)it1.next();
			String to_filename = map.get(from_filename);
		
			File f = new File(path+from_filename);
			BufferedReader br = null;
			try {
				br = new BufferedReader(new FileReader(f));
				String tmp = null;
				while((tmp = br.readLine())!=null)
					file.add(tmp);
				br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			for(int i=0;i<n;i++){
				Instruction ins = inslist.get(i);
				if(ins.getname().equals(from_filename)){
					if(ins.gettype()=='D'){
						int line = ins.getline()-1;
						int col  = ins.getcol()-1;
						char[] ca = file.get(line).toCharArray();
						for(int j=col;ca[j]!=';';j++)
							ca[j] = ' ';
						StringBuilder sb = new StringBuilder();
						for(int j=0;j<ca.length;j++)
							sb.append(ca[j]);
						String s = sb.toString();
						file.set(line, s);
					}
					else if(ins.gettype()=='P'){
						int line = ins.getline()-1;
						int col  = ins.getcol()-1;
						char[] ca = file.get(line).toCharArray();
						ArrayList<Character> carray = new ArrayList<Character>();
						for(int j=0;j<ca.length;j++)
							carray.add(ca[j]);
						int index;
						for(index=col;ca[index]!=';';index++)
							;
						index++;
						char[] pc = ins.gettext().toCharArray();
						for(int j=0;j<pc.length;j++,index++)
							carray.add(index,pc[j]);
						StringBuilder sb = new StringBuilder();
						for(int j=0;j<carray.size();j++)
							sb.append(carray.get(j));
						String s = sb.toString();
						file.set(line, s);
					}
					//A
					else{
						int line = ins.getline()-1;
						int col  = ins.getcol()-1;
						char[] ca = file.get(line).toCharArray();
						ArrayList<Character> carray = new ArrayList<Character>();
						for(int j=0;j<ca.length;j++)
							carray.add(ca[j]);
						char[] ac = ins.gettext().toCharArray();
						for(int j=col,k=0;k<ac.length;j++,k++)
							carray.add(j, ac[k]);
						StringBuilder sb = new StringBuilder();
						for(int j=0;j<carray.size();j++)
							sb.append(carray.get(j));
						String s = sb.toString();
						file.set(line, s);
					}
					int size = file.size();
					File out = new File(path+to_filename);
					BufferedWriter bw=new BufferedWriter(new FileWriter(out));
					for(int j=0;j<size;j++)
					{
						bw.write(file.get(j));
						bw.newLine();
					}
					bw.close();
				}
			}
		}
		
		Iterator<String> it2 = map.keySet().iterator();  
		while(it2.hasNext()){
			String from_filename 	= (String)it2.next();
			String to_filename 		= map.get(from_filename);
			String patchname		= id + from_filename + ".patch";
			
			from_filename		= path + "/" + from_filename;
			to_filename			= path + "/" + to_filename;
			patchname			= path + "/" + patchname;
			
			String command 		= "diff -uN "+from_filename + " " + to_filename;
			
			//System.out.println("To execute cmd: " + command);
			
			Process process = Runtime.getRuntime().exec(command);			
			
			InputStream fis = process.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(fis));
			String line = null;
			File f = new File(patchname);	
			BufferedWriter bw=new BufferedWriter(new FileWriter(f));
			
			while((line = br.readLine())!=null)
			{
				bw.write(line);
				bw.newLine();
			}
			bw.close();
			process.waitFor();
		}
	}
}

class InsSort implements Comparator <Instruction>
{
	public int compare(Instruction ins1,Instruction ins2){
		if((ins1.gettype()=='D' && ins2.gettype()!='D') || (ins1.gettype()=='P' && ins2.gettype()=='A')
			|| (ins1.gettype()!='D' && ins2.gettype()!='D' && ins1.getcol()>ins2.getcol()))
			return -1;
		else
			return 1;
	}
}










