package org.incava.doctorj;

import java.io.*;
import java.util.*;
import org.incava.analysis.*;
import org.incava.io.Find;
import org.incava.java.*;
import org.incava.log.Log;
import org.incava.util.TimedEvent;
import org.incava.util.TimedEventSet;


public class Main
{
    private TimedEventSet totalInit = new TimedEventSet();

    private TimedEventSet totalParse = new TimedEventSet();

    private TimedEventSet totalAnalysis = new TimedEventSet();

    private JavaParser parser = null;

    private Report report = null;

    private JavaParserVisitor analyzer = new JavadocAnalyzer(report);

    public void run(String[] args)
    {
        Options  opts  = Options.get();
        String[] names = opts.process(args);

        Log.log("names: " + names);

        if (Log.verbose) {
            TreeSet  propKeys = new TreeSet(System.getProperties().keySet());
            Iterator it       = propKeys.iterator();
            while (it.hasNext()) {
                String propKey = (String)it.next();
                Log.log("" + propKey + ": " + System.getProperty(propKey));
            }
        }

        if (opts.emacsOutput) {
            report = new TerseReport(System.out);
        }
        else {
            report = new ContextReport(System.out);
        }
        
        analyzer = new JavadocAnalyzer(report);

        Log.log("getting file list");
        String[] fileNames = Find.getFileList(names, ".java");

        for (int ni = 0; ni < fileNames.length; ++ni) { // we are the fileNames that say "ni"!
            processFile(fileNames[ni]);
        }

        if (fileNames.length > 1) {
            long total = totalInit.duration + totalParse.duration + totalAnalysis.duration;
            Log.log("time: total: " + total + "; init: " + totalInit.duration + "; parse: " + totalParse.duration + "; analysis: " + totalAnalysis.duration + "; #files: " + fileNames.length);
        }
    }

    protected void processFile(String fileName)
    {
        Log.log("file: " + fileName);

        TimedEvent init = new TimedEvent(totalInit);
        try {
            report.reset(new File(fileName));
                
            FileInputStream fis = new FileInputStream(fileName);

            if (parser == null) {
                String src = Options.get().source;
                if (src.equals("1.3")) {
                    Log.log("creating 1.3 parser");
                    parser = new Java13Parser(fis);
                }
                else if (src.equals("1.4")) {
                    Log.log("creating 1.4 parser");
                    parser = new Java14Parser(fis);
                }
                else {
                    System.err.println("ERROR: source version '" + src + "' not recognized");
                    System.exit(-1);
                }
            }
            else {
                parser.ReInit(fis);
            }
            init.end();
        }
        catch (FileNotFoundException e) {
            System.out.println("File " + fileName + " not found.");
            return;
        }
        catch (IOException e) {
            System.out.println("Error opening " + fileName + ": " + e);
            return;
        }

        Log.log("running parser");
            
        try {
            TimedEvent         parse = new TimedEvent(totalParse);
            ASTCompilationUnit cu    = parser.CompilationUnit();
            parse.end();

            TimedEvent analysis = new TimedEvent(totalAnalysis);
            cu.jjtAccept(analyzer, null);
            report.flush();
            analysis.end();

            long total = init.duration + parse.duration + analysis.duration;
            Log.log("time: total: " + total + "; init: " + init.duration + "; parse: " + parse.duration + "; analysis: " + analysis.duration + "; " + fileName);
        }
        catch (ParseException e) {
            System.out.println("Parse error in " + fileName + ": " + e.getMessage());
        }
    }

    public static void main(String[] args)
    {
        Main m = new Main();
        m.run(args);
    }

}
