/**
  * File: FirstTokenizer.java
  * Content: Retrieves the methods with body in a program, returning the line number and
  *    the method signature in a ordered list.
  *    The method to obtain the methods is quite simplistic, that's the reason because
  *    the logic is implemented on a different file, to make it easier to change the
  *    logic to some better algorithm
  * Author: LuisM Pena
  * Date: 21st March 2001
  * Version: 0.60.00
  * Last change:
  *
  *
  **/

package preprocessors;

import sensei.util.Parameters;
import sensei.util.ParameterException;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.LineNumberReader;
import java.util.Iterator;
import java.util.Vector;

public class IncludeTraceCode
{
  IncludeTraceCode(String init)
  {
    this.init=init;
  }

  void process(File file) throws IOException
  {
    getLinesToChange(file);

    LineNumberReader reader=null;
    PrintWriter writer = null;

    try
    {
      File backup=new File(file.toString()+SecExtension);
      File orig=new File(file.toString());
      if (!orig.renameTo(backup))
        System.out.println("Error: could not rename file " + orig + " into " + backup);
      else
      {
        reader=new LineNumberReader(new InputStreamReader(new FileInputStream(backup)));
        writer = new PrintWriter(new FileOutputStream(file));

        String traceLine=prepareTraceLine(init, file);
        String line=reader.readLine();
        while(line!=null)
        {
          if (lineNumberToChange(reader.getLineNumber()))
          {
            writer.println(createTraceLine(traceLine));
            if (isNotTraceCodeLine(line))
              writer.println(line);
          }
          else
            writer.println(line);
          line=reader.readLine();
        }
      }
    }
    finally
    {
      if (writer!=null) try {writer.close();}catch(Exception ex){}
      if (reader!=null) try {reader.close();}catch(Exception ex){}
    }
  }

  String createTraceLine(String start)
  {
    String ret = start + lineInfo.signature + "\");";
    getNextLineInfo();
    return ret;
  }

  String prepareTraceLine(String init, File file)
  {
    return init + "Trace.code(\"" + file.getName() + " -> ";
  }

  boolean isNotTraceCodeLine(String line)
  {
    return line.indexOf("Trace.code")==-1;  //no perfect! regex, eh?
  }

  void getLinesToChange(File file) throws IOException
  {
    lines=tokenizer.process(file).iterator();
    getNextLineInfo();
  }

  void getNextLineInfo()
  {
    lineInfo = lines.hasNext()? (FirstTokenizer.Line) lines.next() : null;
  }

  boolean lineNumberToChange(int line)
  {
    return (lineInfo!=null) && (lineInfo.line==line);
  }

  FirstTokenizer tokenizer = new FirstTokenizer();
  Iterator lines;
  FirstTokenizer.Line lineInfo;
  String init;

//*************************************************************************************//
//**************************** MAIN ***************************************************//
//*************************************************************************************//

  /**
    * Main function, just checks the arguments and passes it to the PreprocessDebug class
    **/
  public static void main(String args[])
  {
    try
    {
      Vector validParams=new Vector();
      validParams.add(TabParameter);
      validParams.add(SpaceParameter);
      validParams.add(NoBackupParameter);
      Parameters param=new Parameters(args, validParams, new Vector(), 1, Integer.MAX_VALUE);

      String init="    ";  //ok, hardcoded so far

      IncludeTraceCode prep = new IncludeTraceCode(init);

      for (int i=0; i < param.getArgumentsLength() ; i++)
        prep.process(new File(param.getArgument(i)));

    }
    catch(ParameterException ex)
    {
      System.out.println(ex.getMessage());
      System.out.println("Use: [-tab tabuladores] [-sp spaces] [-nobackup] file [files]");
    }
    catch(IOException ex)
    {
      System.out.println(ex);
    }
  }

  static final String TabParameter="tab";
  static final String SpaceParameter="sp";
  static final String NoBackupParameter="nobackup";
  static final String SecExtension=".noprep";
}