package minijaja.compilateur;

import minijaja.exception.*;
import minijaja.jjtree.*;
import minijaja.controleurtype.*;

import java.io.*;

public class CompilateurMiniJaja {
	public Node arbreAnalyse;
	public Reader minijaja;
	public String fileout;
	
	public CompilateurMiniJaja(Reader minijaja){
		this.minijaja = minijaja;
		arbreAnalyse = null;
		fileout = "out.jjc";
	}
	
	public CompilateurMiniJaja(Reader minijaja, String fileout){
		this.minijaja = minijaja;
		arbreAnalyse = null;
		this.fileout = fileout;
	}
	
	private Object executeVisitor(MiniJajaVisitor visitor, Object data) throws MiniJajaVisitorException  {
		return this.arbreAnalyse.jjtAccept(visitor,data);
	}
	
	public void parse() throws MiniJajaParseurException {
		try{
			MiniJaja parser = new MiniJaja(this.minijaja);
		    parser.classe();
		    arbreAnalyse = parser.getJJTree().rootNode();
		}catch(ParseException e){
			throw new MiniJajaParseurException(e.getMessage());
		}
	}
	
	public void controleType() throws MiniJajaControleurTypeException {
		ControleurTypeData ctdata = new ControleurTypeData();
		try{
			
		    boolean ret = (Boolean)this.executeVisitor(new ControleurTypeMiniJajaVisitor(),ctdata);
		}catch(MiniJajaVisitorException e){
			throw new MiniJajaControleurTypeException(e.toString());
		}
	}

	public void compile() throws MiniJajaCompilateurException {
		try{
			String compil = (String)this.executeVisitor(new CompileMiniJajaVisitor(),new CompilateurData());
			// On l'enregistre dans un fichier
	        FileWriter flux = new FileWriter(this.fileout);
	        BufferedWriter buffer = new BufferedWriter(flux);
	        buffer.write(compil);
	        buffer.flush();
	        buffer.close();
	        flux.close();
		}catch(IOException e){
			throw new MiniJajaCompilateurException(e.getMessage());
		}catch(MiniJajaVisitorException e){
			throw new MiniJajaCompilateurException(e.toString());
		}
	}
	
	public void compileMiniJaja() throws MiniJajaVisitorException {
		try{
			// On Parse le fichier de Minijaja
			this.parse();
			// On effectue le controle de type dessus
			this.controleType();
			// On genere le JajaCode
			this.compile();
		}catch(MiniJajaVisitorException e){
			throw new MiniJajaCompilationProcessusException(e.toString());
		}
	}
	
	
	public static void main(String args[]) throws Exception {
		
		CompilateurMiniJaja compilateur;
		
		// CompilateurMiniJaja compilateur = new CompilateurMiniJaja(new FileReader(new File("./src/minijaja/exemple.txt")));
		
		if(args.length>=1 && args.length<=2){
		
			if(args.length==1){
				compilateur = new CompilateurMiniJaja(new FileReader(new File(args[0])));
			}else{
				compilateur = new CompilateurMiniJaja(new FileReader(new File(args[0])),args[1]);
			}
			try{
			    compilateur.compileMiniJaja();
			}catch(MiniJajaVisitorException e){
				System.err.println(e.toString());
			}
		}else{
			System.err.println("USAGE : fichierMiniJaja [fichierJajaCode]");
		}
		
		
		
		
	    
	}

}
