/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jdo.tck.util;

import java.io.PrintStream;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestFailure;
import junit.framework.TestResult;
import junit.textui.ResultPrinter;

/**
 * Default result printer implementation for running tests in batch mode.
 *
 * @author Michael Bouschen
 */
public class BatchResultPrinter extends ResultPrinter {
  private static final DecimalFormat THREE_DIGITS_FORMATTER = new DecimalFormat("000");

  /** The stream to delegate the output. */
  private ConsoleFileOutput consoleFileOutput;

  /** The time elapsed to run a test suite. */
  private long runtime;

  /**
   * @param consoleFileOutput console file output
   */
  public BatchResultPrinter(ConsoleFileOutput consoleFileOutput) {
    this(new PrintStream(consoleFileOutput));
    this.consoleFileOutput = consoleFileOutput;
  }

  /**
   * @param writer the writer
   */
  public BatchResultPrinter(PrintStream writer) {
    super(writer);
  }

  /** Called in case of a test error. */
  @Override
  public void addError(Test test, Throwable t) {
    getWriter().print("   ERROR");
  }

  /** Called in case of a test failure. */
  @Override
  public void addFailure(Test test, AssertionFailedError t) {
    getWriter().print("   FAILURE");
  }

  /** Called when a test case is finished. */
  @Override
  public void endTest(Test test) {
    getWriter().println();
  }

  /** Called when a test case is started. */
  @Override
  public void startTest(Test test) {
    String testName;
    if (test instanceof TestCase) {
      testName = getClassBaseName(test) + "." + ((TestCase) test).getName();
    } else {
      testName = test.toString();
    }
    getWriter().print("RUN " + testName + '\t');
    getWriter().flush();
  }

  /**
   * @see ResultPrinter#elapsedTimeAsString(long)
   */
  @Override
  protected String elapsedTimeAsString(long runTime) {
    return THREE_DIGITS_FORMATTER.format((double) runTime / 1000);
  }

  /** */
  @Override
  protected void printHeader(long runTime) {
    this.runtime = runTime;
    getWriter().println("Description: " + System.getProperty("jdo.tck.description"));
    getWriter().println("Time: " + elapsedTimeAsString(runTime));
  }

  /** */
  @Override
  protected void printFooter(TestResult result) {
    String message = null;
    if (this.consoleFileOutput != null) {
      message = getResultMessage(result, this.consoleFileOutput);
      String directory = this.consoleFileOutput.getDirectory();
      ResultSummary.appendTCKResultMessage(directory, message);
      ResultSummary.save(directory, result);
    } else {
      message = getResultMessage(result);
    }

    if (!result.wasSuccessful()) {
      getWriter().println("FAILURES!!!");
      printErrorSummary(result);
    }

    getWriter().println(message);
    getWriter().println("Excluded tests: " + System.getProperty("jdo.tck.exclude"));
  }

  // helper method

  /**
   * Returns the result message for the given result instance and the given console file output
   * instance.
   *
   * @param result the result instance
   * @param consoleFileOutput the console file output instance
   * @return the result message
   */
  private String getResultMessage(TestResult result, ConsoleFileOutput consoleFileOutput) {
    String message = this.consoleFileOutput.getFileName() + ':';
    message += System.getProperty("line.separator") + "    ";
    message += getResultMessage(result);
    return message;
  }

  /**
   * Returns the result message for the given result instance.
   *
   * @param result the result instance
   * @return the result message
   */
  private String getResultMessage(TestResult result) {
    boolean success = result.wasSuccessful();
    String message = success ? "OK " : "** ";
    message +=
        "Tests run: "
            + THREE_DIGITS_FORMATTER.format(result.runCount())
            + ", Time: "
            + elapsedTimeAsString(this.runtime)
            + " seconds.";
    if (!success) {
      message += " Failures: " + result.failureCount() + ", Errors: " + result.errorCount();
    }
    return message;
  }

  /**
   * @return Name of the class of the given object without package prefix
   */
  private String getClassBaseName(Object obj) {
    if (obj == null) return null;
    String className = obj.getClass().getName();
    int index = className.lastIndexOf('.');
    if (index != -1) {
      className = className.substring(index + 1);
    }
    return className;
  }

  private void printErrorSummary(TestResult result) {
    Object[] array = getSortedArrayOfErrorSummaryEntries(result);
    if (array.length > 0) {
      getWriter().println("Error summary:");
      for (Object o : array) {
        getWriter().println(o);
      }
    }
  }

  private static Object[] getSortedArrayOfErrorSummaryEntries(TestResult result) {
    Map<String, ErrorSummaryEntry> map = new HashMap<>();
    for (Enumeration<TestFailure> e = result.errors(); e.hasMoreElements(); ) {
      TestFailure testFailure = e.nextElement();
      Throwable t = testFailure.thrownException();
      String message = getRootCause(t).toString();
      ErrorSummaryEntry errorSummaryEntry = map.get(message);
      if (errorSummaryEntry == null) {
        errorSummaryEntry = new ErrorSummaryEntry(t);
        map.put(message, errorSummaryEntry);
      }
      errorSummaryEntry.count++;
    }

    Object[] array = map.values().toArray();
    Arrays.sort(array);
    return array;
  }

  private static Throwable getRootCause(Throwable t) {
    while (t.getCause() != null) {
      t = t.getCause();
    }
    return t;
  }

  private static class ErrorSummaryEntry implements Comparable<ErrorSummaryEntry> {
    private int count = 0;
    private final Throwable t;

    private ErrorSummaryEntry(Throwable t) {
      this.t = t;
    }

    public boolean equals(Object o) {
      return compareTo((ErrorSummaryEntry) o) == 0;
    }

    public int hashCode() {
      return this.count;
    }

    public int compareTo(ErrorSummaryEntry o) {
      int result = this.count - o.count;
      if (result == 0) {
        String message1 = getRootCause().toString();
        String message2 = o.getRootCause().toString();
        result = message1.compareTo(message2);
      }
      return result;
    }

    public String toString() {
      StringBuilder buffer = new StringBuilder(THREE_DIGITS_FORMATTER.format(count));
      buffer.append(" error");
      if (this.count != 1) {
        buffer.append("s: ");
      } else {
        buffer.append(":  ");
      }
      buffer.append(getRootCause());
      return buffer.toString();
    }

    private Throwable getRootCause() {
      return BatchResultPrinter.getRootCause(this.t);
    }
  }
}
