package org.testng;

import java.util.ArrayList;
import java.util.HashMap;
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 =
    new HashMap<ITestResult, List<Integer>>();

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

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

  private static synchronized void log(String s, ITestResult m) {
    // 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 = new ArrayList<Integer>();
      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());
    }
  }

  private static ITestResult  getCurrentTestResult() {
    return m_currentTestResult.get();
  }

  private static void ppp(String s) {
    System.out.println("[Reporter] " + s);
  }

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

    return result;
  }

//  public static void setCurrentOutput(List<String> tmr) {
//    m_output = tmr;
////    m_localResult.set(tmr);
//  }

//  public static List<String> getCurrentOutput() {
//    return m_output;
////    List<String> result = (List<String>) m_localResult.get();
////    return result;
//  }

}
