package org.testng;

import org.testng.collections.Lists;
import org.testng.collections.Maps;

import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * This class is used for test methods to log messages that will be
 * included in the HTML reports generated by TestNG.
 * <br>
 * <br>
 * <b>Implementation details.</b>
 * <br>
 * <br>
 * The reporter keeps a combined output of strings (in m_output) and also
 * a record of which method output which line.  In order to do this, callers
 * specify what the current method is with setCurrentMethod() and the
 * Reporter maintaing a mapping of each method with a list of integers.
 * These integers are indices in the combined output (avoids duplicating
 * the output).
 *
 * Created on Nov 2, 2005
 * @author cbeust
 */
public class Reporter {
  // when tests are run in parallel, each thread may be working with different
  // 'current test result'. Also, this value should be inherited if the test code
  // spawns its own thread.
  private static ThreadLocal<ITestResult> m_currentTestResult = new InheritableThreadLocal<ITestResult>();

  /**
   * All output logged in a sequential order.
   */
  private static List<String> m_output = new Vector<String>();

  private static Map<ITestResult, List<Integer>> m_methodOutputMap = Maps.newHashMap();

  public static void setCurrentTestResult(ITestResult m) {
    m_currentTestResult.set(m);
  }

  public static List<String> getOutput() {
    return m_output;
  }

  /**
   * Erase the content of all the output generated so far.
   */
  public static void clear() {
    m_methodOutputMap.clear();
    m_output.clear();
  }

  private static synchronized void log(String s, ITestResult m) {
    // Escape for the HTML reports
    s = s.replace("<", "[").replace(">", "]") + "<br>";

    // synchronization needed to ensure the line number and m_output are updated atomically
    int n = getOutput().size();
    List<Integer> lines = m_methodOutputMap.get(m);
    if (lines == null) {
      lines = Lists.newArrayList();
      m_methodOutputMap.put(m, lines);
    }
    lines.add(n);
    getOutput().add(s);
  }

  /**
   * Log the passed string to the HTML reports
   * @param s The message to log
   */
  public static void log(String s) {
    log(s, getCurrentTestResult());
  }

  /**
   * Log the passed string to the HTML reports if the current verbosity
   * is equal or greater than the one passed in parameter. If logToStandardOut
   * is true, the string will also be printed on standard out.
   *
   * @param s The message to log
   * @param level The verbosity of this message
   * @param logToStandardOut Whether to print this string on standard
   * out too
   */
  public static void log(String s, int level, boolean logToStandardOut) {
    if (TestRunner.getVerbose() >= level) {
      log(s, getCurrentTestResult());
      if (logToStandardOut) {
        System.out.println(s);
      }
    }
  }

  /**
   * Log the passed string to the HTML reports.  If logToStandardOut
   * is true, the string will also be printed on standard out.
   *
   * @param s The message to log
   * @param logToStandardOut Whether to print this string on standard
   * out too
   */
  public static void log(String s, boolean logToStandardOut) {
    log(s, getCurrentTestResult());
    if (logToStandardOut) {
      System.out.println(s);
    }
  }
  /**
   * Log the passed string to the HTML reports if the current verbosity
   * is equal or greater than the one passed in parameter
   *
   * @param s The message to log
   * @param level The verbosity of this message
   */
  public static void log(String s, int level) {
    if (TestRunner.getVerbose() >= level) {
      log(s, getCurrentTestResult());
    }
  }

  /**
   * @return the current test result.
   */
  public static ITestResult getCurrentTestResult() {
    return m_currentTestResult.get();
  }

  public static synchronized List<String> getOutput(ITestResult tr) {
    List<String> result = Lists.newArrayList();
    List<Integer> lines = m_methodOutputMap.get(tr);
    if (lines != null) {
      for (Integer n : lines) {
        result.add(getOutput().get(n));
      }
    }

    return result;
  }
}
