
package org.eclipse.releng.build.tools.comparator;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class is responsible for extracting the relevent "Debug" messages from
 * the huge maven debug log.
 * 
 * @author davidw
 * 
 */
public class Extractor {

    public final static String  BUILD_DIRECTORY_PROPERTY = "builddirectory";
    public final static String  COMPARATOR_REPO_PROPERTY = "comparatorRepo";
    private static final String EOL                      = System.getProperty("line.separator", "\n");

    public static void main(final String[] args) {
        final Extractor extractor = new Extractor();
        if (args.length > 0) {
            extractor.setBuildDirectory(args[0]);
        } else {
            // can set explicitly for local test
            // does not have to be a full "download", only
            // I20130910-0800/buildlogs/mb060_run-maven-build_output.txt
            extractor.setBuildDirectory("/home/davidw/temp/I20130910-0800");
        }
        try {
            extractor.processBuildfile();
        }
        catch (final IOException e) {
            e.printStackTrace();
        }
    }

    private final String  debugFilename                         = "mb060_run-maven-build_output.txt";
    private final String  outputFilenameFull                    = "buildtimeComparatorFull.log.txt";
    private final String  outputFilenameSign                    = "buildtimeComparatorSignatureOnly.log.txt";
    private final String  outputFilenameSignPlusInnerJar        = "buildtimeComparatorSignatureOnlyWithInnerJar.log.txt";
    private final String  outputFilenameDoc                     = "buildtimeComparatorDocBundle.log.txt";
    private final String  outputFilenameOther                   = "buildtimeComparatorUnanticipated.log.txt";
    private final String  outputFilenamejdtCore                 = "buildtimeComparatorJDTCore.log.txt";
    private final String  buildlogsDirectory                    = "buildlogs";
    private final String  comparatorLogsDirectory               = "comparatorlogs";
    private String        comparatorRepo                        = "comparatorRepo";
    private String        buildDirectory;
    private String        inputFilename;
    private String        outputFilenameFullLog;
    private String        outputFilenameSignLog;
    private String        outputFilenameDocLog;
    private String        outputFilenameOtherLog;
    private String        outputFilenameSignPlusInnerJarLog;
    private String        outputFilenamejdtCoreLog;
    private final String  mainregexPattern                      = "^\\[WARNING\\].*eclipse.platform.releng.aggregator/(.*)/pom.xml: baseline and build artifacts have same version but different contents";
    private final Pattern mainPattern                           = Pattern.compile(mainregexPattern);
    private final String  noclassifierregexPattern              = "^.*no-classifier:.*$";
    private final Pattern noclassifierPattern                   = Pattern.compile(noclassifierregexPattern);
    private final String  classifier_sourcesregexPattern        = "^.*classifier-sources:.*$";
    private final Pattern classifier_sourcesPattern             = Pattern.compile(classifier_sourcesregexPattern);
    private final String  classifier_sourcesfeatureregexPattern = "^.*classifier-sources-feature:.*$";
    private final Pattern classifier_sourcesfeaturePattern      = Pattern.compile(classifier_sourcesfeatureregexPattern);

    private final String  sign1regexPattern                     = "^.*META-INF/ECLIPSE_.RSA.*$";
    private final Pattern sign1Pattern                          = Pattern.compile(sign1regexPattern);
    private final String  sign2regexPattern                     = "^.*META-INF/ECLIPSE_.SF.*$";
    private final Pattern sign2Pattern                          = Pattern.compile(sign2regexPattern);
    private final String  docNameregexPattern                   = "^.*eclipse\\.platform\\.common.*\\.doc\\..*$";
    private final Pattern docNamePattern                        = Pattern.compile(docNameregexPattern);
    // jar pattern added for bug 416701
    private final String  jarregexPattern                       = "^.*\\.jar.*$";
    private final Pattern jarPattern                            = Pattern.compile(jarregexPattern);
    private int           count;
    private int           countSign;
    private int           countDoc;
    private int           countOther;
    private int           countSignPlusInnerJar;
    private int           countJDTCore;

    public Extractor() {

    }

    private boolean docItem(final LogEntry newEntry) {
        boolean result = false;
        final String name = newEntry.getName();
        final Matcher matcher = docNamePattern.matcher(name);
        if (matcher.matches()) {
            result = true;
        }
        return result;
    }

    public String getBuildDirectory() {
        // if not set explicitly, see if its a system property
        if (buildDirectory == null) {
            buildDirectory = System.getProperty(BUILD_DIRECTORY_PROPERTY);
        }
        return buildDirectory;
    }

    private String getInputFilename() {
        if (inputFilename == null) {
            inputFilename = getBuildDirectory() + "/" + buildlogsDirectory + "/" + debugFilename;
        }
        return inputFilename;
    }

    private String getOutputFilenameDoc() {
        if (outputFilenameDocLog == null) {
            outputFilenameDocLog = getBuildDirectory() + "/" + buildlogsDirectory + "/" + comparatorLogsDirectory + "/"
                    + outputFilenameDoc;
        }
        return outputFilenameDocLog;
    }

    private String getOutputFilenameFull() {
        if (outputFilenameFullLog == null) {
            outputFilenameFullLog = getBuildDirectory() + "/" + buildlogsDirectory + "/" + comparatorLogsDirectory + "/"
                    + outputFilenameFull;
        }
        return outputFilenameFullLog;
    }

    private String getOutputFilenameOther() {
        if (outputFilenameOtherLog == null) {
            outputFilenameOtherLog = getBuildDirectory() + "/" + buildlogsDirectory + "/" + comparatorLogsDirectory + "/"
                    + outputFilenameOther;
        }
        return outputFilenameOtherLog;
    }

    private String getOutputFilenameSign() {
        if (outputFilenameSignLog == null) {
            outputFilenameSignLog = getBuildDirectory() + "/" + buildlogsDirectory + "/" + comparatorLogsDirectory + "/"
                    + outputFilenameSign;
        }
        return outputFilenameSignLog;
    }

    private String getOutputFilenameSignWithInnerJar() {
        if (outputFilenameSignPlusInnerJarLog == null) {
            outputFilenameSignPlusInnerJarLog = getBuildDirectory() + "/" + buildlogsDirectory + "/" + comparatorLogsDirectory
                    + "/" + outputFilenameSignPlusInnerJar;
        }
        return outputFilenameSignPlusInnerJarLog;
    }

    private String getOutputFilenameJDTCore() {
        if (outputFilenamejdtCoreLog == null) {
            outputFilenamejdtCoreLog = getBuildDirectory() + "/" + buildlogsDirectory + "/" + comparatorLogsDirectory + "/"
                    + outputFilenamejdtCore;
        }
        return outputFilenamejdtCoreLog;
    }

    public void processBuildfile() throws IOException {

        // Make sure directory exists
        File outputDir = new File(getBuildDirectory() + "/" + buildlogsDirectory, comparatorLogsDirectory);
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }

        final File infile = new File(getInputFilename());
        final Reader in = new FileReader(infile);
        BufferedReader input = null;
        input = new BufferedReader(in);
        final File outfile = new File(getOutputFilenameFull());
        final Writer out = new FileWriter(outfile);
        final BufferedWriter output = new BufferedWriter(out);

        final File outfileSign = new File(getOutputFilenameSign());
        final Writer outsign = new FileWriter(outfileSign);
        final BufferedWriter outputSign = new BufferedWriter(outsign);

        final File outfileSignWithInnerJar = new File(getOutputFilenameSignWithInnerJar());
        final Writer outsignWithJar = new FileWriter(outfileSignWithInnerJar);
        final BufferedWriter outputSignWithJar = new BufferedWriter(outsignWithJar);

        final File outfileJDTCore = new File(getOutputFilenameJDTCore());
        final Writer outJDTCore = new FileWriter(outfileJDTCore);
        final BufferedWriter outputJDTCore = new BufferedWriter(outJDTCore);

        final File outfileDoc = new File(getOutputFilenameDoc());
        final Writer outdoc = new FileWriter(outfileDoc);
        final BufferedWriter outputDoc = new BufferedWriter(outdoc);

        final File outfileOther = new File(getOutputFilenameOther());
        final Writer outother = new FileWriter(outfileOther);
        final BufferedWriter outputOther = new BufferedWriter(outother);

        writeHeader(output);
        writeHeader(outputSign);
        writeHeader(outputSignWithJar);
        writeHeader(outputDoc);
        writeHeader(outputOther);
        writeHeader(outputJDTCore);
        count = 0;
        countSign = 0;
        countSignPlusInnerJar = 0;
        countDoc = 0;
        countOther = 0;
        countJDTCore = 0;
        try {
            String inputLine = "";

            while (inputLine != null) {
                inputLine = input.readLine();
                if (inputLine != null) {
                    final Matcher matcher = mainPattern.matcher(inputLine);
                    if (matcher.matches()) {

                        final LogEntry newEntry = new LogEntry();
                        newEntry.setName(matcher.group(1));
                        // read and write differences, until next blank line
                        do {
                            inputLine = input.readLine();
                            if ((inputLine != null) && (inputLine.length() > 0)) {
                                newEntry.addReason(inputLine);
                            }
                        }
                        while ((inputLine != null) && (inputLine.length() > 0));
                        // //output.write(EOL);
                        // now, do one more, to get the "info" that says
                        // what was copied, or not.
                        do {
                            inputLine = input.readLine();
                            if ((inputLine != null) && (inputLine.length() > 0)) {
                                // except leave out the first line, which is a
                                // long [INFO] line repeating what we already
                                // know.
                                if (!inputLine.startsWith("[INFO]")) {
                                    newEntry.addInfo(inputLine);
                                }
                            }
                        }
                        while ((inputLine != null) && (inputLine.length() > 0));
                        // Write full log, for sanity check, if nothing else
                        writeEntry(++count, output, newEntry);
                        if (jdtCore(newEntry)) {
                            writeEntry(++countJDTCore, outputJDTCore, newEntry);
                        } else if (docItem(newEntry)) {
                            writeEntry(++countDoc, outputDoc, newEntry);
                        } else if (pureSignature(newEntry)) {
                            writeEntry(++countSign, outputSign, newEntry);
                        } else if (pureSignaturePlusInnerJar(newEntry)) {
                            writeEntry(++countSignPlusInnerJar, outputSignWithJar, newEntry);
                        } else {
                            writeEntry(++countOther, outputOther, newEntry);
                        }
                    }
                }
            }
        }
        finally {
            if (input != null) {
                input.close();
            }
            if (output != null) {
                output.close();
            }
            if (outputSign != null) {
                outputSign.close();
            }
            if (outputDoc != null) {
                outputDoc.close();
            }
            if (outputOther != null) {
                outputOther.close();
            }
            if (outputSignWithJar != null) {
                outputSignWithJar.close();
            }
            if (outputJDTCore != null) {
                outputJDTCore.close();
            }
        }
    }

    private void writeHeader(final BufferedWriter output) throws IOException {
        output.write("Comparator differences from current build" + EOL);
        output.write("\t" + getBuildDirectory() + EOL);
        if (comparatorRepo != null) {
            output.write("compared to reference repo at " + EOL);
            output.write("\t" + getComparatorRepo() + EOL + EOL);
        }
    }

    private boolean jdtCore(final LogEntry newEntry) {
        boolean result = false;
        final String name = newEntry.getName();
        if (name.equals("eclipse.jdt.core/org.eclipse.jdt.core")) {
            result = true;
        }
        return result;
    }

    private boolean pureSignature(final LogEntry newEntry) {
        // if all lines match one of these critical patterns,
        // then assume "signature only" difference. If even
        // one of them does not match, assume not.
        boolean result = true;
        final List<String> reasons = newEntry.getReasons();
        for (final String reason : reasons) {
            final Matcher matcher1 = noclassifierPattern.matcher(reason);
            final Matcher matcher2 = classifier_sourcesPattern.matcher(reason);
            final Matcher matcher3 = classifier_sourcesfeaturePattern.matcher(reason);
            final Matcher matcher4 = sign1Pattern.matcher(reason);
            final Matcher matcher5 = sign2Pattern.matcher(reason);

            if (matcher1.matches() || matcher2.matches() || matcher3.matches() || matcher4.matches() || matcher5.matches()) {
                continue;
            } else {
                result = false;
                break;
            }
        }

        return result;
    }

    private boolean pureSignaturePlusInnerJar(final LogEntry newEntry) {
        // if all lines match one of these critical patterns,
        // then assume "signature only plus inner jar" difference. If even
        // one of them does not match, assume not.
        // TODO: refactor so less copy/paste of pureSignature method.
        boolean result = true;
        final List<String> reasons = newEntry.getReasons();
        for (final String reason : reasons) {
            final Matcher matcher1 = noclassifierPattern.matcher(reason);
            final Matcher matcher2 = classifier_sourcesPattern.matcher(reason);
            final Matcher matcher3 = classifier_sourcesfeaturePattern.matcher(reason);
            final Matcher matcher4 = sign1Pattern.matcher(reason);
            final Matcher matcher5 = sign2Pattern.matcher(reason);
            final Matcher matcher6 = jarPattern.matcher(reason);

            if (matcher1.matches() || matcher2.matches() || matcher3.matches() || matcher4.matches() || matcher5.matches()
                    || matcher6.matches()) {
                continue;
            } else {
                result = false;
                break;
            }
        }

        return result;
    }

    public void setBuildDirectory(final String buildDirectory) {
        this.buildDirectory = buildDirectory;
    }

    private void writeEntry(int thistypeCount, final Writer output, final LogEntry newEntry) throws IOException {

        output.write(thistypeCount + ".  " + newEntry.getName() + EOL);
        final List<String> reasons = newEntry.getReasons();
        for (final String reason : reasons) {
            output.write(reason + EOL);
        }
        final List<String> infolist = newEntry.getInfo();
        for (final String info : infolist) {
            output.write(info + EOL);
        }
        output.write(EOL);
    }

    public String getComparatorRepo() {
        return comparatorRepo;
    }

    public void setComparatorRepo(String comparatorRepo) {
        this.comparatorRepo = comparatorRepo;
    }
}
