package org.testng;

import org.testng.collections.Lists;
import org.testng.collections.Maps;
import org.testng.internal.AnnotationTypeEnum;
import org.testng.internal.Attributes;
import org.testng.internal.IConfiguration;
import org.testng.internal.IInvoker;
import org.testng.internal.Utils;
import org.testng.internal.annotations.IAnnotationFinder;
import org.testng.internal.thread.ThreadUtil;
import org.testng.reporters.JUnitXMLReporter;
import org.testng.reporters.TestHTMLReporter;
import org.testng.reporters.TextReporter;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;

import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <CODE>SuiteRunner</CODE> is responsible for running all the tests included in one
 * suite. The test start is triggered by {@link #run()} method.
 *
 * @author Cedric Beust, Apr 26, 2004
 */
public class SuiteRunner implements ISuite, Serializable, IInvokedMethodListener {

  /* generated */
  private static final long serialVersionUID = 5284208932089503131L;

  private static final String DEFAULT_OUTPUT_DIR = "test-output";

  private Map<String, ISuiteResult> m_suiteResults = Maps.newHashMap();
  transient private List<TestRunner> m_testRunners = Lists.newArrayList();
  transient private List<ISuiteListener> m_listeners = Lists.newArrayList();
  transient private TestListenerAdapter m_textReporter = new TestListenerAdapter();

  private String m_outputDir; // DEFAULT_OUTPUT_DIR;
  private XmlSuite m_suite;

  transient private List<ITestListener> m_testListeners = Lists.newArrayList();
  transient private ITestRunnerFactory m_tmpRunnerFactory;

  transient private ITestRunnerFactory m_runnerFactory;
  transient private boolean m_useDefaultListeners = true;

  // The remote host where this suite was run, or null if run locally
  private String m_host;

  // The configuration
  transient private IConfiguration m_configuration;

  transient private ITestObjectFactory m_objectFactory;
  transient private Boolean m_skipFailedInvocationCounts = Boolean.FALSE;

  transient private IMethodInterceptor m_methodInterceptor;
  private List<IInvokedMethodListener> m_invokedMethodListeners;

  /** The list of all the methods invoked during this run */
  private List<IInvokedMethod> m_invokedMethods =
      Collections.synchronizedList(Lists.<IInvokedMethod>newArrayList());

//  transient private IAnnotationTransformer m_annotationTransformer = null;

  public SuiteRunner(IConfiguration configuration, XmlSuite suite,
      String outputDir)
  {
    this(configuration, suite, outputDir, null);
  }

  public SuiteRunner(IConfiguration configuration, XmlSuite suite, String outputDir,
      ITestRunnerFactory runnerFactory)
  {
    this(configuration, suite, outputDir, runnerFactory, false);
  }

  public SuiteRunner(IConfiguration configuration,
      XmlSuite suite,
      String outputDir,
      ITestRunnerFactory runnerFactory,
      boolean useDefaultListeners)
  {
    this(configuration, suite, outputDir, runnerFactory, useDefaultListeners,
        null /* method interceptor */,
        null /* invoked method listeners */,
        null /* test listeners */);
  }

  protected SuiteRunner(IConfiguration configuration,
      XmlSuite suite,
      String outputDir,
      ITestRunnerFactory runnerFactory,
      boolean useDefaultListeners,
      IMethodInterceptor methodInterceptor,
      List<IInvokedMethodListener> invokedMethodListeners,
      List<ITestListener> testListeners)
  {
    init(configuration, suite, outputDir, runnerFactory, useDefaultListeners,
      methodInterceptor, invokedMethodListeners, testListeners);
  }

  private void init(IConfiguration configuration,
    XmlSuite suite,
    String outputDir,
    ITestRunnerFactory runnerFactory,
    boolean useDefaultListeners,
    IMethodInterceptor methodInterceptor,
    List<IInvokedMethodListener> invokedMethodListener,
    List<ITestListener> testListeners)
  {
    m_configuration = configuration;
    m_suite = suite;
    m_useDefaultListeners = useDefaultListeners;
    m_tmpRunnerFactory= runnerFactory;
    m_methodInterceptor = methodInterceptor;
    setOutputDir(outputDir);
    m_objectFactory = m_configuration.getObjectFactory();
    if(m_objectFactory == null) {
      m_objectFactory = suite.getObjectFactory();
    }
    m_invokedMethodListeners = invokedMethodListener;
    // Add our own IInvokedMethodListener
    if (m_invokedMethodListeners == null) {
      m_invokedMethodListeners = Lists.newArrayList();
    }
    m_invokedMethodListeners.add(this);

    m_skipFailedInvocationCounts = suite.skipFailedInvocationCounts();
    if (null != testListeners) {
      m_testListeners.addAll(testListeners);
    }
    m_runnerFactory = buildRunnerFactory();
    for (XmlTest test : m_suite.getTests()) {
      TestRunner tr = m_runnerFactory.newTestRunner(this, test, m_invokedMethodListeners);

      //
      // Install the method interceptor, if any was passed
      //
      if (m_methodInterceptor != null) {
        tr.setMethodInterceptor(m_methodInterceptor);
      }

      // Reuse the same text reporter so we can accumulate all the results
      // (this is used to display the final suite report at the end)
      tr.addListener(m_textReporter);
      m_testRunners.add(tr);
    }
  }

  @Override
  public XmlSuite getXmlSuite() {
    return m_suite;
  }

  @Override
  public String getName() {
    return m_suite.getName();
  }

  public void setObjectFactory(ITestObjectFactory objectFactory) {
    m_objectFactory = objectFactory;
  }

  public void setReportResults(boolean reportResults) {
    m_useDefaultListeners = reportResults;
  }

  private void invokeListeners(boolean start) {
    for (ISuiteListener sl : m_listeners) {
      if (start) {
        sl.onStart(this);
      }
      else {
        sl.onFinish(this);
      }
    }
  }

  private void setOutputDir(String outputdir) {
    if (((null == outputdir) || "".equals(outputdir.trim()))
        && m_useDefaultListeners) {
      outputdir= DEFAULT_OUTPUT_DIR;
    }

    m_outputDir = (null != outputdir) ? new File(outputdir).getAbsolutePath()
        : null;
  }

  private ITestRunnerFactory buildRunnerFactory() {
    ITestRunnerFactory factory = null;

    if (null == m_tmpRunnerFactory) {
      factory = new DefaultTestRunnerFactory(m_configuration,
          m_testListeners.toArray(new ITestListener[m_testListeners.size()]),
          m_useDefaultListeners, m_skipFailedInvocationCounts);
    }
    else {
      factory = new ProxyTestRunnerFactory(
          m_testListeners.toArray(new ITestListener[m_testListeners.size()]),
          m_tmpRunnerFactory);
    }

    return factory;
  }

  @Override
  public String getParallel() {
    return m_suite.getParallel();
  }

  @Override
  public void run() {
    invokeListeners(true /* start */);
    try {
      privateRun();
    }
    finally {
      invokeListeners(false /* stop */);
    }
  }

  private void privateRun() {

    // Map for unicity, Linked for guaranteed order
    Map<Method, ITestNGMethod> beforeSuiteMethods= new LinkedHashMap<Method, ITestNGMethod>();
    Map<Method, ITestNGMethod> afterSuiteMethods = new LinkedHashMap<Method, ITestNGMethod>();

    IInvoker invoker = null;

    // Get the invoker and find all the suite level methods
    for (TestRunner tr: m_testRunners) {
      // TODO: Code smell.  Invoker should belong to SuiteRunner, not TestRunner
      // -- cbeust
      invoker = tr.getInvoker();

      for (ITestNGMethod m : tr.getBeforeSuiteMethods()) {
        beforeSuiteMethods.put(m.getMethod(), m);
      }

      for (ITestNGMethod m : tr.getAfterSuiteMethods()) {
        afterSuiteMethods.put(m.getMethod(), m);
      }
    }

    //
    // Invoke beforeSuite methods (the invoker can be null
    // if the suite we are currently running only contains
    // a <file-suite> tag and no real tests)
    //
    if (invoker != null) {
      if(beforeSuiteMethods.values().size() > 0) {
        invoker.invokeConfigurations(null,
            beforeSuiteMethods.values().toArray(new ITestNGMethod[beforeSuiteMethods.size()]),
            m_suite, m_suite.getParameters(), null, /* no parameter values */
            null /* instance */
        );
      }

      Utils.log("SuiteRunner", 3, "Created " + m_testRunners.size() + " TestRunners");

      //
      // Run all the test runners
      //
      boolean testsInParallel = XmlSuite.PARALLEL_TESTS.equals(m_suite.getParallel());
      if (!testsInParallel) {
        runSequentially();
      }
      else {
        runInParallelTestMode();
      }

//      SuitePlan sp = new SuitePlan();
//      for (TestRunner tr : m_testRunners) {
//        sp.addTestPlan(tr.getTestPlan());
//      }

//      sp.dump();

      //
      // Invoke afterSuite methods
      //
      if (afterSuiteMethods.values().size() > 0) {
        invoker.invokeConfigurations(null,
              afterSuiteMethods.values().toArray(new ITestNGMethod[afterSuiteMethods.size()]),
              m_suite, m_suite.getAllParameters(), null, /* no parameter values */

              null /* instance */);
      }
    }
  }

  private List<IReporter> m_reporters = Lists.newArrayList();

  private void addReporter(IReporter listener) {
    m_reporters.add(listener);
  }

  public List<IReporter> getReporters() {
    return m_reporters;
  }

  private void runSequentially() {
    for (TestRunner tr : m_testRunners) {
      runTest(tr);
    }
  }

  private void runTest(TestRunner tr) {
    tr.run();

    ISuiteResult sr = new SuiteResult(m_suite, tr);
    m_suiteResults.put(tr.getName(), sr);
  }

  /**
   * Implement <suite parallel="tests">.
   * Since this kind of parallelism happens at the suite level, we need a special code path
   * to execute it.  All the other parallelism strategies are implemented at the test level
   * in TestRunner#createParallelWorkers (but since this method deals with just one <test>
   * tag, it can't implement <suite parallel="tests">, which is why we're doing it here).
   */
  private void runInParallelTestMode() {
    List<Runnable> tasks= Lists.newArrayList(m_testRunners.size());
    for(TestRunner tr: m_testRunners) {
      tasks.add(new SuiteWorker(tr));
    }

    ThreadUtil.execute(tasks, m_suite.getThreadCount(),
        m_suite.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS), false);
  }

  private class SuiteWorker implements Runnable {
      private TestRunner m_testRunner;

      public SuiteWorker(TestRunner tr) {
        m_testRunner = tr;
      }

      @Override
      public void run() {
        Utils.log("[SuiteWorker]", 4, "Running XML Test '"
                  +  m_testRunner.getTest().getName() + "' in Parallel");
        runTest(m_testRunner);
      }
  }

  /**
   * Registers ISuiteListeners interested in reporting the result of the current
   * suite.
   *
   * @param reporter
   */
  protected void addListener(ISuiteListener reporter) {
    m_listeners.add(reporter);
  }

  @Override
  public void addListener(ITestNGListener listener) {
    if (listener instanceof IInvokedMethodListener) {
      m_invokedMethodListeners.add((IInvokedMethodListener) listener);
    } else if (listener instanceof ISuiteListener) {
      addListener((ISuiteListener) listener);
    } else if (listener instanceof IReporter) {
      addReporter((IReporter) listener);
    } else {
      throw new AssertionError("Trying to add unsupported listener:" + listener);
    }
  }

  @Override
  public String getOutputDirectory() {
    return m_outputDir + File.separatorChar + getName();
  }

  @Override
  public Map<String, ISuiteResult> getResults() {
    return m_suiteResults;
  }

  /**
   * FIXME: should be removed?
   *
   * @see org.testng.ISuite#getParameter(java.lang.String)
   */
  @Override
  public String getParameter(String parameterName) {
    return m_suite.getParameter(parameterName);
  }

  /**
   * @see org.testng.ISuite#getMethodsByGroups()
   */
  @Override
  public Map<String, Collection<ITestNGMethod>> getMethodsByGroups() {
    Map<String, Collection<ITestNGMethod>> result = Maps.newHashMap();

    for (TestRunner tr : m_testRunners) {
      ITestNGMethod[] methods = tr.getAllTestMethods();
      for (ITestNGMethod m : methods) {
        String[] groups = m.getGroups();
        for (String groupName : groups) {
          Collection<ITestNGMethod> testMethods = result.get(groupName);
          if (null == testMethods) {
            testMethods = Lists.newArrayList();
            result.put(groupName, testMethods);
          }
          testMethods.add(m);
        }
      }
    }

    return result;
  }

  /**
   * @see org.testng.ISuite#getInvokedMethods()
   */
  @Override
  public Collection<ITestNGMethod> getInvokedMethods() {
    return getIncludedOrExcludedMethods(true /* included */);
  }

  /**
   * @see org.testng.ISuite#getExcludedMethods()
   */
  @Override
  public Collection<ITestNGMethod> getExcludedMethods() {
    return getIncludedOrExcludedMethods(false/* included */);
  }

  private Collection<ITestNGMethod> getIncludedOrExcludedMethods(boolean included) {
    List<ITestNGMethod> result= Lists.newArrayList();

    for (TestRunner tr : m_testRunners) {
      Collection<ITestNGMethod> methods = included ? tr.getInvokedMethods() : tr.getExcludedMethods();
      for (ITestNGMethod m : methods) {
        result.add(m);
      }
    }

    return result;
  }

  @Override
  public IObjectFactory getObjectFactory() {
    return m_objectFactory instanceof IObjectFactory ? (IObjectFactory) m_objectFactory : null;
  }

  @Override
  public IObjectFactory2 getObjectFactory2() {
    return m_objectFactory instanceof IObjectFactory2 ? (IObjectFactory2) m_objectFactory : null;
  }

  /**
   * Returns the annotation finder for the given annotation type.
   * @param pAnnotationType the annotation type
   * @return the annotation finder for the given annotation type.
   */
  @Override
  public IAnnotationFinder getAnnotationFinder(String pAnnotationType) {
    AnnotationTypeEnum annotationType = AnnotationTypeEnum.valueOf(pAnnotationType);
    if (AnnotationTypeEnum.JDK != annotationType) {
      throw new TestNGException("Javadoc annotations are no longer supported. Either" +
      " update your tests to JDK annotations or use TestNG 5.11.");
    }
    return m_configuration.getAnnotationFinder();
  }

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

  /**
   * The default implementation of {@link ITestRunnerFactory}.
   */
  private static class DefaultTestRunnerFactory implements ITestRunnerFactory {
    private ITestListener[] m_failureGenerators;
    private boolean m_useDefaultListeners;
    private boolean m_skipFailedInvocationCounts;
    private IConfiguration m_configuration;

    public DefaultTestRunnerFactory(IConfiguration configuration,
        ITestListener[] failureListeners,
        boolean useDefaultListeners,
        boolean skipFailedInvocationCounts)
    {
      m_configuration = configuration;
      m_failureGenerators = failureListeners;
      m_useDefaultListeners = useDefaultListeners;
      m_skipFailedInvocationCounts = skipFailedInvocationCounts;
    }

    @Override
    public TestRunner newTestRunner(ISuite suite, XmlTest test,
        List<IInvokedMethodListener> listeners) {
      boolean skip = m_skipFailedInvocationCounts;
      if (! skip) {
        skip = test.skipFailedInvocationCounts();
      }
      TestRunner testRunner = new TestRunner(m_configuration, suite, test,
          suite.getOutputDirectory(), suite.getAnnotationFinder(test.getAnnotations()), skip,
          listeners);

      if (m_useDefaultListeners) {
        testRunner.addListener(new TestHTMLReporter());
        testRunner.addListener(new JUnitXMLReporter());

        //TODO: Moved these here because maven2 has output reporters running
        //already, the output from these causes directories to be created with
        //files. This is not the desired behaviour of running tests in maven2.
        //Don't know what to do about this though, are people relying on these
        //to be added even with defaultListeners set to false?
        testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose()));
      }

      for (ITestListener itl : m_failureGenerators) {
        testRunner.addListener(itl);
      }

      return testRunner;
    }
  }

  private static class ProxyTestRunnerFactory implements ITestRunnerFactory {
    private ITestListener[] m_failureGenerators;
    private ITestRunnerFactory m_target;

    public ProxyTestRunnerFactory(ITestListener[] failureListeners, ITestRunnerFactory target) {
      m_failureGenerators = failureListeners;
      m_target= target;
    }

    @Override
    public TestRunner newTestRunner(ISuite suite, XmlTest test,
        List<IInvokedMethodListener> listeners) {
      TestRunner testRunner= m_target.newTestRunner(suite, test, listeners);

      testRunner.addListener(new TextReporter(testRunner.getName(), TestRunner.getVerbose()));

      for (ITestListener itl : m_failureGenerators) {
        testRunner.addListener(itl);
      }

      return testRunner;
    }
  }

  public void setHost(String host) {
    m_host = host;
  }

  @Override
  public String getHost() {
    return m_host;
  }

  private SuiteRunState m_suiteState= new SuiteRunState();

  /**
   * @see org.testng.ISuite#getSuiteState()
   */
  @Override
  public SuiteRunState getSuiteState() {
    return m_suiteState;
  }

  public void setSkipFailedInvocationCounts(Boolean skipFailedInvocationCounts) {
    if (skipFailedInvocationCounts != null) {
      m_skipFailedInvocationCounts = skipFailedInvocationCounts;
    }
  }

  private IAttributes m_attributes = new Attributes();

  @Override
  public Object getAttribute(String name) {
    return m_attributes.getAttribute(name);
  }

  @Override
  public void setAttribute(String name, Object value) {
    m_attributes.setAttribute(name, value);
  }

  @Override
  public Set<String> getAttributeNames() {
    return m_attributes.getAttributeNames();
  }

  @Override
  public Object removeAttribute(String name) {
    return m_attributes.removeAttribute(name);
  }

  /////
  // implements IInvokedMethodListener
  //

  @Override
  public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
    if (method == null) {
      throw new NullPointerException("Method should not be null");
    }
    m_invokedMethods.add(method);
  }

  @Override
  public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
  }

  //
  // implements IInvokedMethodListener
  /////

  @Override
  public List<IInvokedMethod> getAllInvokedMethods() {
    return m_invokedMethods;
  }
}
