package LogParser;

import java.io.*;
import java.util.*;
import java.text.*;

public class LogParser
{
   private final int TYPE_END      = 3;
   private final int DATE_START    = 5;
   //private final int DATE_END      = 33;
   private int ACTUAL_DATE_END     = DATE_START;
   //private final int FILE_START    = 52; //+19
   private int ACTUAL_FILE_START   = DATE_START;
   //private final int METHOD_START  = 56; //+23
   private int ACTUAL_METHOD_START = DATE_START;
   private final int CORRECT_START = 21;
   //private final int CORRECT_END   = 25;
   
   private String         filename;
   private XMLLog         xml_out;

   public LogParser(String name)
   {
      filename = name;
      xml_out  = null;
   } // end ctor(String)
   
   public void read()
   {
      try
      {
         BufferedReader in = new BufferedReader(
                             new FileReader(filename));
         XMLLog_SessionEntry  xml_se  = null;
         XMLLog_FileEntry     xml_fe  = null;
         XMLLog_MethodEntry   xml_me  = null;
         XMLLog_TestCaseEntry xml_tce = null;
         
         // this is to skip the ID line of the file
         String id = in.readLine();
         id = id.substring(4);
         String currentLine = in.readLine();
         ACTUAL_DATE_END = DATE_START; // reset to search for date end
         // some computers may output date in different format,
         // so we need to find the end of it
         findRealDateEnd(currentLine);
         int type      = -1;
         int last_type = -1;
         xml_out = new XMLLog(id);
         while(currentLine != null)
         {
            type = Integer.parseInt(
                                   currentLine.substring(0,TYPE_END));
//            System.out.println(type);
            if(type == 0)
            {
//               System.out.println("Session");
               if(last_type == 0)
               {
                  xml_out.addEntry(xml_se);
                  xml_se = null;
               } // end if
               else if(last_type == 1)
               {
                  xml_se.addEntry(xml_fe);
                  xml_out.addEntry(xml_se);
                  xml_se = null;
                  xml_fe = null;
               } // end else if
               else if(last_type == 10 || last_type > 100)
               {
                  xml_fe.addEntry(xml_me);
                  xml_se.addEntry(xml_fe);
                  xml_out.addEntry(xml_se);
                  xml_se = null;
                  xml_fe = null;
                  xml_me = null;
               } // end else if
               
               xml_se = new XMLLog_SessionEntry();
               xml_se.setTimestamp(parseDate(currentLine));
            } // end if
            else if(type == 1)
            {
//               System.out.println("File");
               if(last_type == 1)
               {
                  xml_se.addEntry(xml_fe);
                  xml_fe = null;
               } // end else if
               else if(last_type == 10 || last_type > 100)
               {
                  xml_fe.addEntry(xml_me);
                  xml_se.addEntry(xml_fe);
                  xml_fe = null;
                  xml_me = null;
               } // end else if
               
               xml_fe = new XMLLog_FileEntry();
               xml_fe.setTimestamp(parseDate(currentLine));
               xml_fe.setName(currentLine.substring(ACTUAL_FILE_START,
                                               currentLine.length()));
            } // end else if
            else if(type == 10)
            {
//               System.out.println("Method");
               if(last_type == 10 || last_type > 100)
               {
                  xml_fe.addEntry(xml_me);
                  xml_me = null;
               } // end if
               
               xml_me = new XMLLog_MethodEntry();
               xml_me.setTimestamp(parseDate(currentLine));
               xml_me.setName(currentLine.substring(ACTUAL_METHOD_START,
                                               currentLine.length()));
            } // end else if
            else if(type > 100)
            {
//               System.out.println("Testcase");
               xml_tce = new XMLLog_TestCaseEntry();
               xml_tce.setTimestamp(parseDate(currentLine));
               int numArgs = type % 100;
               for(int i = 0; i < numArgs; ++i)
               {
                  String reformatted = "";
                  String temp = in.readLine();
                  for(int j = 0; j < temp.length(); ++j)
                  {
                     if(temp.charAt(j) == '<') reformatted += "&lt;";
                     else if(temp.charAt(j) == '>') reformatted += "&gt;";
                     else reformatted += temp.charAt(j);
                  } // end for
                  xml_tce.addArg(reformatted);
               } // end for
               
               currentLine = in.readLine();
               if(currentLine.subSequence(CORRECT_START,
                                 currentLine.length()).equals("true"))
                  xml_tce.setCorrect(true);
               else xml_tce.setCorrect(false);
               
               xml_me.addEntry(xml_tce);
            } // end else if
            
            last_type = type;
            currentLine = in.readLine();
         } // end while
         
         if(last_type == 0)
         {
            xml_out.addEntry(xml_se);
            xml_se = null;
         } // end if
         else if(last_type == 1)
         {
            xml_se.addEntry(xml_fe);
            xml_out.addEntry(xml_se);
            xml_se = null;
            xml_fe = null;
         } // end else if
         else if(last_type == 10 || last_type > 100)
         {
            xml_fe.addEntry(xml_me);
            xml_se.addEntry(xml_fe);
            xml_out.addEntry(xml_se);
            xml_se = null;
            xml_fe = null;
            xml_me = null;
         } // end else if
         
         in.close();
      } // end try
      catch(FileNotFoundException fnfe) { System.out.println("Error 1"); }
      catch(IOException ioe) { System.out.println("Error 2"); }
      catch(Throwable t) { System.out.println("Malformed log file "+
                           filename); t.printStackTrace();}
   } // end read()
   
   private Date parseDate(String date)
   {
      Date timestamp  = null;
      date            = date.substring(DATE_START, ACTUAL_DATE_END);
      
      try
      {
         SimpleDateFormat sdf = new SimpleDateFormat();
         sdf.applyPattern("EEE MMM dd hh:mm:ss z yyyy");
         timestamp = sdf.parse(date);
      } // end try
      catch(ParseException pe) { System.out.println(pe); }
      
      return timestamp;
   } // end parseDate(String)
   
   private void findRealDateEnd(String search)
   {
      while(!(search.charAt(ACTUAL_DATE_END+1) == ':' &&
              search.charAt(ACTUAL_DATE_END+2) == ' '))
         ++ACTUAL_DATE_END;
      
      ++ACTUAL_DATE_END;
      ACTUAL_FILE_START   = ACTUAL_DATE_END + 19;
      ACTUAL_METHOD_START = ACTUAL_DATE_END + 23;
      
      //System.out.println(""+ACTUAL_DATE_END+"\n"+ACTUAL_FILE_START+"\n"+ACTUAL_METHOD_START);
   } // end findRealDateEnd(String)
   
   public void write()
   {
      try
      {
         FileWriter fw = new FileWriter("xml_"+filename+".xml");
                                     //filename.substring(0, filename.length())+
                                     //".xml");
         fw.write(xml_out.toString());
         fw.flush();
         fw.close();
      } // end try
      catch(IOException ioe) { System.out.println(ioe); }
   } // end write()
   
   public XMLLog getLog(String filename)
   {
      this.filename = filename;
      read();
      return xml_out;
   } // end
   
   public static void main(String[] args)
   {
      if(args.length < 1)
      {
         System.out.println("Usage is java LogReader <tcra_log to parse>");
         return;
      } // end if
      
      LogParser lp = new LogParser(args[0]);
      lp.read();
      lp.write();
   } // end main(String[])
} // end class
