/*
 * Created on 2004-08-30
 *
 * Part of the Symbian development plug-in for Eclipse
 * Copyright (C) Mikołaj Zalewski, 2004
 */
package pl.zalewski.mikolaj.symbdev.skins;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import org.eclipse.core.runtime.Path;

import pl.zalewski.mikolaj.symbdev.launch.SymbianLaunchConfigurationDelegate;

/**
 * This class is responsible for rewriting the epoc.ini file e.g. to
 * add a skin
 * 
 * @author mikolaj
 */
public class EpocIniRewriter {

    /**
     * Creates a new rewriter
     */
    public EpocIniRewriter(File in, File out) {
        super();
        fIn=in;
        fOut=out;
    }
    
    static public final String EPOC_INI_PATH="epoc32/data/epoc.ini";
    static public final String ECLIPSE_EPOC_INI_PATH="epoc32/data/"+SymbianLaunchConfigurationDelegate.EPOC_CUSTOM_MACHINE+".ini";
    
    static public EpocIniRewriter createStdRewriter(String epocRoot)
    {
        EpocIniRewriter w=new EpocIniRewriter(new Path(epocRoot).append(EPOC_INI_PATH).toFile(),
                new Path(epocRoot).append(ECLIPSE_EPOC_INI_PATH).toFile());
        w.addBeginningWriter(new FirstCommentWriter());
        return w;
    }
    
    /**
     * Adds a writer rule. It is executed at the beginning of the
     * genereation of the epoc.eclipse.ini file in the order in which
     * they were added
     * @param writerRule The rule
     */
    public void addBeginningWriter(IWriterRule writerRule)
    {
        fBeginningWriters.add(writerRule);
    }

    /**
     * Adds a append rule. It is executed at the end of the
     * genereation of the epoc.eclipse.ini file in the order in which
     * they were added
     * @param writerRule The rule
     */
    public void addAppendWriter(IWriterRule writerRule)
    {
        fAppendWriters.add(writerRule);
    }
    
    /**
     * Adds a rewriter. Rewriters are executed in the beginning, at the end
     * and if a token for which they are registered is found
     * @param token The token (first word in a line)
     * @param rule The rule to execute
     */
    public void addRewriter(String token, IRewriterRule rule)
    {
        fRewriters.put(token.toLowerCase(), rule);
    }
    
    /**
     * Does the rewrite according to the writers/rewriters that were registerd
     */
    public void rewrite()
    	throws IOException
    {
        FileInputStream inputs=null;
        
        FileOutputStream outputs=new FileOutputStream(fOut);
        OutputStreamWriter writer=new OutputStreamWriter(outputs);
        BufferedWriter output=new BufferedWriter(writer);
        
        try {
	        Iterator it=fBeginningWriters.iterator();
	        while (it.hasNext())
	        {
	            IWriterRule rule=(IWriterRule)it.next();
	            rule.write(output);
	        }
	        
	        inputs=new FileInputStream(fIn);
	        InputStreamReader reader=new InputStreamReader(inputs);
	        BufferedReader input=new BufferedReader(reader);
	        
	        it=fRewriters.values().iterator();
	        while (it.hasNext())
	        {
	            IRewriterRule rule=(IRewriterRule)it.next();
	            rule.fileBegin(output);
	        }
	        
	        String line;
	        while ((line=input.readLine())!=null)
	        {
	            String[] lt=line.split("\\s+", 2);
	            if (lt.length==0)
	                continue;
	            String cmd=lt[0].toLowerCase();
	            String args;
	            if (lt.length==2) args=lt[1];
	                else args="";
	            
	            IRewriterRule rule=(IRewriterRule)fRewriters.get(cmd);
	            if (rule!=null)
	                rule.rewrite(lt[0], args, output);
	            else {
	            	output.write(line);
	            	output.newLine();
	            }
	        }
	        
	        it=fRewriters.values().iterator();
	        while (it.hasNext())
	        {
	            IRewriterRule rule=(IRewriterRule)it.next();
	            rule.fileEnd(output);
	        }                    
	
	        it=fAppendWriters.iterator();
	        while (it.hasNext())
	        {
	            IWriterRule rule=(IWriterRule)it.next();
	            rule.write(output);
	        }
        }
        finally
        {
            output.close();
            writer.close();
            outputs.close();
      
            if (inputs!=null) inputs.close();
        }
    }
    
    File fIn, fOut;
    LinkedList fBeginningWriters=new LinkedList();
    LinkedList fAppendWriters=new LinkedList();
    HashMap fRewriters=new HashMap();
}
