/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed 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 com.google.gwt.junit;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.shared.impl.StringCase;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Runs via browsers managed by Selenium.
 */
public class RunStyleSelenium extends RunStyle {

  /**
   * The maximum amount of time that a selenia can take to start in
   * milliseconds. 10 minutes.
   */
  private static final int LAUNCH_TIMEOUT = 10 * 60 * 1000;

  /**
   * Wraps a Selenium instance.
   */
  protected static interface SeleniumWrapper {
    void createSelenium(String domain);

    Selenium getSelenium();

    String getSpecifier();
  }

  /**
   * Implements SeleniumWrapper using DefaultSelenium. Visible for testing.
   */
  static class RCSelenium implements SeleniumWrapper {

    private static final Pattern PATTERN = Pattern.compile("([\\w\\.-]+):([\\d]+)/(.+)");

    /*
     * Visible for testing.
     */
    String browser;
    String host;
    int port;

    private Selenium selenium;
    private final String specifier;

    public RCSelenium(String specifier) {
      this.specifier = specifier;
      parseSpecifier();
    }

    public void createSelenium(String domain) {
      this.selenium = new DefaultSelenium(host, port, browser, domain);
    }

    public Selenium getSelenium() {
      return selenium;
    }

    public String getSpecifier() {
      return specifier;
    }

    private void parseSpecifier() {
      Matcher matcher = PATTERN.matcher(specifier);
      if (!matcher.matches()) {
        throw new IllegalArgumentException("Unable to parse Selenium target "
            + specifier + " (expected format is [host]:[port]/[browser])");
      }
      this.browser = matcher.group(3);
      this.host = matcher.group(1);
      this.port = Integer.parseInt(matcher.group(2));
    }
  }

  /**
   * A {@link Thread} used to interact with {@link Selenium} instances. Selenium
   * does not support execution of multiple methods at the same time, so its
   * important to make sure that {@link SeleniumThread#isComplete()} returns
   * true before calling more methods in {@link Selenium}.
   */
  class SeleniumThread extends Thread {

    /**
     * {@link RunStyleSelenium#lock} is sometimes active when calling
     * {@link #isComplete()}, so we need a separate lock to avoid deadlock.
     */
    Object accessLock = new Object();

    /**
     * The exception thrown while running this thread, if any.
     */
    private Throwable exception;

    /**
     * True if the selenia has successfully completed the action. Protected by
     * {@link #accessLock}.
     */
    private boolean isComplete;

    private final SeleniumWrapper remote;

    /**
     * Construct a new {@link SeleniumThread}.
     * 
     * @param remote the {@link SeleniumWrapper} instance
     */
    public SeleniumThread(SeleniumWrapper remote) {
      this.remote = remote;
      setDaemon(true);
    }

    /**
     * Get the {@link Throwable} caused by the action.
     * 
     * @return the exception if one occurred, null if none occurred
     */
    public Throwable getException() {
      synchronized (accessLock) {
        return exception;
      }
    }

    public SeleniumWrapper getRemote() {
      return remote;
    }

    public boolean isComplete() {
      synchronized (accessLock) {
        return isComplete;
      }
    }

    protected void markComplete() {
      synchronized (accessLock) {
        isComplete = true;
      }
    }

    protected void setException(Throwable e) {
      synchronized (accessLock) {
        this.exception = e;
        isComplete = true;
      }
    }
  }

  /**
   * <p>
   * The {@link Thread} used to launch a module on a single Selenium target. We
   * launch {@link Selenium} instances in a separate thread because
   * {@link Selenium#start()} can hang if the browser cannot be opened
   * successfully. Instead of blocking the test indefinitely, we use a separate
   * thread and timeout if needed.
   * </p>
   * <p>
   * We wait until {@link LaunchThread#isComplete()} returns <code>true</code>
   * before starting the keep alive thread or creating a {@link StopThread}, so
   * no other thread can be accessing {@link Selenium} at the same time.
   * </p>
   */
  class LaunchThread extends SeleniumThread {

    private final String moduleName;

    /**
     * Construct a new {@link LaunchThread}.
     * 
     * @param remote the remote {@link SeleniumWrapper} instance
     * @param moduleName the module to load
     */
    public LaunchThread(SeleniumWrapper remote, String moduleName) {
      super(remote);
      this.moduleName = moduleName;
    }

    @Override
    public void run() {
      SeleniumWrapper remote = getRemote();
      try {
        String domain = "http://" + getLocalHostName() + ":" + shell.getPort()
            + "/";
        String url = shell.getModuleUrl(moduleName);

        // Create the selenium instance and open the browser.
        if (shell.getTopLogger().isLoggable(TreeLogger.TRACE)) {
          shell.getTopLogger().log(TreeLogger.TRACE,
              "Starting with domain: " + domain + " Opening URL: " + url);
        }
        remote.createSelenium(domain);
        remote.getSelenium().start();

        // We set the speed to 1000ms as a workaround a bug where Selenium#open
        // can hang.
        remote.getSelenium().setSpeed("1000");
        remote.getSelenium().open(url);
        remote.getSelenium().setSpeed("0");

        markComplete();
      } catch (Throwable e) {
        shell.getTopLogger().log(
            TreeLogger.ERROR,
            "Error launching browser via Selenium-RC at "
                + remote.getSpecifier(), e);
        setException(e);
      }
    }
  }

  /**
   * <p>
   * The {@link Thread} used to stop a selenium instance.
   * </p>
   * <p>
   * We stop the keep alive thread before creating {@link StopThread}s, and we
   * do not create {@link StopThread}s if a {@link LaunchThread} is still
   * running for a {@link Selenium} instance, so no other thread can possible be
   * accessing {@link Selenium} at the same time.
   * </p>
   */
  class StopThread extends SeleniumThread {

    public StopThread(SeleniumWrapper remote) {
      super(remote);
    }

    @Override
    public void run() {
      SeleniumWrapper remote = getRemote();
      try {
        remote.getSelenium().stop();
        markComplete();
      } catch (Throwable e) {
        shell.getTopLogger().log(TreeLogger.WARN,
            "Error stopping selenium session at " + remote.getSpecifier(), e);
        setException(e);
      }
    }
  }

  /**
   * The list of hosts that were interrupted. Protected by {@link #lock}.
   */
  private Set<String> interruptedHosts;

  /**
   * We keep a list of {@link LaunchThread} instances so that we know which
   * selenia successfully started. Only selenia that have been successfully
   * started should be stopped when the test is finished. Protected by
   * {@link #lock};
   */
  private List<LaunchThread> launchThreads = new ArrayList<LaunchThread>();

  /**
   * Indicates that testing has stopped, and we no longer need to run keep alive
   * checks. Protected by {@link #lock}.
   */
  private boolean stopped;

  private SeleniumWrapper remotes[];

  /**
   * A separate lock to control access to {@link Selenium}, {@link #stopped},
   * {@link #remotes}, and {@link #interruptedHosts}. This ensures that the
   * keepAlive thread doesn't call getTitle after the shutdown thread calls
   * {@link Selenium#stop()}.
   */
  private final Object lock = new Object();

  public RunStyleSelenium(final JUnitShell shell) {
    super(shell);
  }

  @Override
  public String[] getInterruptedHosts() {
    synchronized (lock) {
      if (interruptedHosts == null) {
        return null;
      }
      return interruptedHosts.toArray(new String[interruptedHosts.size()]);
    }
  }

  @Override
  public int initialize(String args) {
    if (args == null || args.length() == 0) {
      getLogger().log(TreeLogger.ERROR,
          "Selenium runstyle requires comma-separated Selenium-RC targets");
      return -1;
    }
    String[] targetsIn = args.split(",");
    SeleniumWrapper targets[] = new SeleniumWrapper[targetsIn.length];

    for (int i = 0; i < targets.length; ++i) {
      try {
        targets[i] = createSeleniumWrapper(targetsIn[i]);
      } catch (IllegalArgumentException e) {
        getLogger().log(TreeLogger.ERROR, e.getMessage());
        return -1;
      }
    }

    // We don't need a lock at this point because we haven't started the keep-
    // alive thread.
    this.remotes = targets;

    // Install a shutdown hook that will close all of our outstanding Selenium
    // sessions. The hook is only executed if the JVM is exited normally. If the
    // process is terminated, the shutdown hook will not run, which leaves
    // browser instances open on the Selenium server. We'll need to modify
    // Selenium Server to do its own cleanup after a timeout.
    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        List<StopThread> stopThreads = new ArrayList<StopThread>();
        synchronized (lock) {
          stopped = true;
          for (LaunchThread launchThread : launchThreads) {
            // Closing selenium instances that have not successfully started
            // results in an error on the selenium client. By doing this check,
            // we are ensuring that no other calls to the remote instance are
            // being done by another thread.
            if (launchThread.isComplete()) {
              StopThread stopThread = new StopThread(launchThread.getRemote());
              stopThreads.add(stopThread);
              stopThread.start();
            }
          }
        }

        // Wait for all threads to stop.
        try {
          waitForThreadsToComplete(stopThreads, false, "stop", 500);
        } catch (UnableToCompleteException e) {
          // This should never happen.
        }
      }
    });
    return targets.length;
  }

  @Override
  public void launchModule(String moduleName) throws UnableToCompleteException {
    // Startup all the selenia and point them at the module url.
    for (SeleniumWrapper remote : remotes) {
      LaunchThread thread = new LaunchThread(remote, moduleName);
      synchronized (lock) {
        launchThreads.add(thread);
      }
      thread.start();
    }

    // Wait for all selenium targets to start.
    waitForThreadsToComplete(launchThreads, true, "start", 1000);

    // Check if any threads have thrown an exception. We wait until all threads
    // have had a change to start so that we don't shutdown while some threads
    // are still starting.
    synchronized (lock) {
      for (LaunchThread thread : launchThreads) {
        if (thread.getException() != null) {
          // The thread has already logged the exception.
          throw new UnableToCompleteException();
        }
      }
    }

    // Start the keep alive thread.
    start();
  }

  /**
   * Factory method for {@link SeleniumWrapper}.
   * 
   * @param seleniumSpecifier Specifies the Selenium instance to create
   * @return an instance of {@link SeleniumWrapper}
   */
  protected SeleniumWrapper createSeleniumWrapper(String seleniumSpecifier) {
    return new RCSelenium(seleniumSpecifier);
  }

  /**
   * Create the keep-alive thread.
   */
  protected void start() {
    // This will periodically check for failure of the Selenium session and stop
    // the test if something goes wrong.
    Thread keepAliveThread = new Thread() {
      @Override
      public void run() {
        do {
          try {
            Thread.sleep(1000);
          } catch (InterruptedException ignored) {
            break;
          }
        } while (doKeepAlives());
      }
    };
    keepAliveThread.setDaemon(true);
    keepAliveThread.start();
  }

  private boolean doKeepAlives() {
    synchronized (lock) {
      if (remotes != null) {
        // If the shutdown thread has already executed, then we can stop this
        // thread.
        if (stopped) {
          return false;
        }

        for (SeleniumWrapper remote : remotes) {
          // Use getTitle() as a cheap way to see if the Selenium server's still
          // responding (Selenium seems to provide no way to check the server
          // status directly).
          try {
            if (remote.getSelenium() != null) {
              remote.getSelenium().getTitle();
            }
          } catch (Throwable e) {
            // If we ask for the title of the page while a new module is
            // loading, IE will throw a permission denied exception.
            String message = e.getMessage();
            if (message == null
                || !StringCase.toLower(message).contains("permission denied")) {
              if (interruptedHosts == null) {
                interruptedHosts = new HashSet<String>();
              }
              interruptedHosts.add(remote.getSpecifier());
            }
          }
        }
      }
      return interruptedHosts == null;
    }
  }

  /**
   * Get the display list of specifiers for threads that did not complete.
   * 
   * @param threads the list of threads
   * @return a list of specifiers
   */
  private <T extends SeleniumThread> String getIncompleteSpecifierList(
      List<T> threads) {
    String list = "";
    for (SeleniumThread thread : threads) {
      if (!thread.isComplete()) {
        list += "  " + thread.getRemote().getSpecifier() + "\n";
      }
    }
    return list;
  }

  /**
   * Iterate over a list of {@link SeleniumThread}s, waiting for them to finish.
   * 
   * @param <T> the thread type
   * @param threads the list of threads
   * @param fatalExceptions true to treat all exceptions as errors, false to
   *          treat exceptions as warnings
   * @param action the action being performed by the thread
   * @param sleepTime the amount of time to sleep in milliseconds
   * @throws UnableToCompleteException if the thread times out and
   *           fatalExceptions is true
   */
  private <T extends SeleniumThread> void waitForThreadsToComplete(
      List<T> threads, boolean fatalExceptions, String action, int sleepTime)
      throws UnableToCompleteException {
    boolean allComplete;
    long endTime = System.currentTimeMillis() + LAUNCH_TIMEOUT;
    do {
      try {
        Thread.sleep(sleepTime);
      } catch (InterruptedException e) {
        // This should not happen.
        throw new UnableToCompleteException();
      }

      allComplete = true;
      synchronized (lock) {
        for (SeleniumThread thread : threads) {
          if (!thread.isComplete()) {
            allComplete = false;
          }
        }
      }

      // Check if we have timed out.
      if (!allComplete && endTime < System.currentTimeMillis()) {
        allComplete = true;
        String message = "The following Selenium instances did not " + action
            + " within " + LAUNCH_TIMEOUT + "ms:\n";
        synchronized (lock) {
          message += getIncompleteSpecifierList(threads);
        }
        if (fatalExceptions) {
          shell.getTopLogger().log(TreeLogger.ERROR, message);
          throw new UnableToCompleteException();
        } else {
          shell.getTopLogger().log(TreeLogger.WARN, message);
        }
      }
    } while (!allComplete);
  }
}
