/*
 * 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.dev;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationStateBuilder;
import com.google.gwt.dev.shell.ArtifactAcceptor;
import com.google.gwt.dev.shell.BrowserChannelServer;
import com.google.gwt.dev.shell.BrowserListener;
import com.google.gwt.dev.shell.BrowserWidgetHost;
import com.google.gwt.dev.shell.BrowserWidgetHostChecker;
import com.google.gwt.dev.shell.CheckForUpdates;
import com.google.gwt.dev.shell.ModuleSpaceHost;
import com.google.gwt.dev.shell.OophmSessionHandler;
import com.google.gwt.dev.shell.ShellModuleSpaceHost;
import com.google.gwt.dev.shell.remoteui.RemoteUI;
import com.google.gwt.dev.ui.DevModeUI;
import com.google.gwt.dev.ui.DoneCallback;
import com.google.gwt.dev.ui.DoneEvent;
import com.google.gwt.dev.util.BrowserInfo;
import com.google.gwt.dev.util.arg.ArgHandlerEnableGeneratorResultCaching;
import com.google.gwt.dev.util.arg.ArgHandlerGenDir;
import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerString;

import java.io.File;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Semaphore;

/**
 * The main executable class for the hosted mode shell. This class must not have
 * any GUI dependencies.
 */
public abstract class DevModeBase implements DoneCallback {
  /**
   * Implementation of BrowserWidgetHost that supports the abstract UI
   * interface.
   */
  public class UiBrowserWidgetHostImpl implements BrowserWidgetHost {

    @Override
    public ModuleHandle createModuleLogger(String moduleName, String userAgent, String url,
        String tabKey, String sessionKey, BrowserChannelServer serverChannel, byte[] userAgentIcon) {
      if (sessionKey == null) {
        // if we don't have a unique session key, make one up
        sessionKey = randomString();
      }
      TreeLogger.Type maxLevel = options.getLogLevel();
      String agentTag = BrowserInfo.getShortName(userAgent);
      String remoteSocket = serverChannel.getRemoteEndpoint();
      ModuleHandle module =
          ui.getModuleLogger(userAgent, remoteSocket, url, tabKey, moduleName, sessionKey,
              agentTag, userAgentIcon, maxLevel);
      return module;
    }

    @Override
    public ModuleSpaceHost createModuleSpaceHost(ModuleHandle module, String moduleName)
        throws UnableToCompleteException {
      Event moduleSpaceHostCreateEvent =
          SpeedTracerLogger.start(DevModeEventType.MODULE_SPACE_HOST_CREATE, "Module Name",
              moduleName);
      // TODO(jat): add support for closing an active module
      TreeLogger logger = module.getLogger();
      try {
        // Try to find an existing loaded version of the module def.
        ModuleDef moduleDef = loadModule(logger, moduleName, true);
        assert (moduleDef != null);

        ArchivePreloader.preloadArchives(logger, moduleDef);

        CompilationState compilationState = moduleDef.getCompilationState(logger, compilerContext);
        ShellModuleSpaceHost host =
            doCreateShellModuleSpaceHost(logger, compilationState, moduleDef);
        return host;
      } catch (RuntimeException e) {
        logger.log(TreeLogger.ERROR, "Exception initializing module", e);
        module.unload();
        throw e;
      } finally {
        moduleSpaceHostCreateEvent.end();
      }
    }
  }

  /**
   * Handles the -bindAddress command line flag.
   */
  protected static class ArgHandlerBindAddress extends ArgHandlerString {

    private static final String BIND_ADDRESS_TAG = "-bindAddress";
    private static final String DEFAULT_BIND_ADDRESS = "127.0.0.1";

    private final OptionBindAddress options;

    public ArgHandlerBindAddress(OptionBindAddress options) {
      this.options = options;
    }

    @Override
    public String[] getDefaultArgs() {
      return new String[]{BIND_ADDRESS_TAG, DEFAULT_BIND_ADDRESS};
    }

    @Override
    public String getPurpose() {
      return "Specifies the bind address for the code server and web server " + "(defaults to "
          + DEFAULT_BIND_ADDRESS + ")";
    }

    @Override
    public String getTag() {
      return BIND_ADDRESS_TAG;
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"host-name-or-address"};
    }

    @Override
    public boolean setString(String value) {
      try {
        InetAddress address = InetAddress.getByName(value);
        options.setBindAddress(value);
        if (address.isAnyLocalAddress()) {
          // replace a wildcard address with our machine's local address
          // this isn't fully accurate, as there is no guarantee we will get
          // the right one on a multihomed host
          options.setConnectAddress(InetAddress.getLocalHost().getHostAddress());
        } else {
          options.setConnectAddress(value);
        }
        return true;
      } catch (UnknownHostException e) {
        System.err.println("-bindAddress host \"" + value + "\" unknown");
        return false;
      }
    }
  }

  /**
   * Handles the -blacklist command line argument.
   */
  protected static class ArgHandlerBlacklist extends ArgHandlerString {
    public ArgHandlerBlacklist() {
    }

    @Override
    public String getPurpose() {
      return "Prevents the user browsing URLs that match the specified regexes (comma or space separated)";
    }

    @Override
    public String getTag() {
      return "-blacklist";
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"blacklist-string"};
    }

    @Override
    public boolean setString(String blacklistStr) {
      return BrowserWidgetHostChecker.blacklistRegexes(blacklistStr);
    }
  }

  /**
   * Handles the -codeServerPort command line flag.
   */
  protected static class ArgHandlerCodeServerPort extends ArgHandlerString {

    private static final String CODE_SERVER_PORT_TAG = "-codeServerPort";
    private static final String DEFAULT_PORT = "9997";

    private final OptionCodeServerPort options;

    public ArgHandlerCodeServerPort(OptionCodeServerPort options) {
      this.options = options;
    }

    @Override
    public String[] getDefaultArgs() {
      return new String[]{CODE_SERVER_PORT_TAG, DEFAULT_PORT};
    }

    @Override
    public String getPurpose() {
      return "Specifies the TCP port for the code server (defaults to " + DEFAULT_PORT + ")";
    }

    @Override
    public String getTag() {
      return CODE_SERVER_PORT_TAG;
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"port-number | \"auto\""};
    }

    @Override
    public boolean setString(String value) {
      if (value.equals("auto")) {
        options.setCodeServerPort(0);
      } else {
        try {
          options.setCodeServerPort(Integer.parseInt(value));
        } catch (NumberFormatException e) {
          System.err.println("A port must be an integer or \"auto\"");
          return false;
        }
      }
      return true;
    }
  }

  /**
   * Handles the -logdir command line option.
   */
  protected static class ArgHandlerLogDir extends ArgHandlerString {
    private final OptionLogDir options;

    public ArgHandlerLogDir(OptionLogDir options) {
      this.options = options;
    }

    @Override
    public String getPurpose() {
      return "Logs to a file in the given directory, as well as graphically";
    }

    @Override
    public String getTag() {
      return "-logdir";
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"directory"};
    }

    @Override
    public boolean setString(String value) {
      options.setLogFile(value);
      return true;
    }
  }

  /**
   * Runs a convenient embedded web server.
   */
  protected static class ArgHandlerNoServerFlag extends ArgHandlerFlag {

    private final OptionNoServer options;

    public ArgHandlerNoServerFlag(OptionNoServer options) {
      this.options = options;

      addTagValue("-noserver", false);
    }

    @Override
    public String getPurposeSnippet() {
      return "Starts a servlet container serving the directory specified by the -war flag.";
    }

    @Override
    public String getLabel() {
      return "startServer";
    }

    @Override
    public boolean setFlag(boolean value) {
      options.setNoServer(!value);
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return !options.isNoServer();
    }
  }

  /**
   * Handles the -port command line flag.
   */
  protected static class ArgHandlerPort extends ArgHandlerString {

    private final OptionPort options;

    public ArgHandlerPort(OptionPort options) {
      this.options = options;
    }

    @Override
    public String[] getDefaultArgs() {
      return new String[]{getTag(), "8888"};
    }

    @Override
    public String getPurpose() {
      return "Specifies the TCP port for the embedded web server (defaults to 8888)";
    }

    @Override
    public String getTag() {
      return "-port";
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"port-number | \"auto\""};
    }

    @Override
    public boolean setString(String value) {
      if (value.equals("auto")) {
        options.setPort(0);
      } else {
        try {
          options.setPort(Integer.parseInt(value));
        } catch (NumberFormatException e) {
          System.err.println("A port must be an integer or \"auto\"");
          return false;
        }
      }
      return true;
    }
  }

  /**
   * Handles the -remoteUI command line flag.
   */
  protected static class ArgHandlerRemoteUI extends ArgHandlerString {

    private final HostedModeBaseOptions options;

    public ArgHandlerRemoteUI(HostedModeBaseOptions options) {
      this.options = options;
    }

    @Override
    public String getPurpose() {
      return "Sends Development Mode UI event information to the specified host and port.";
    }

    @Override
    public String getTag() {
      return "-remoteUI";
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"port-number:client-id-string | host-string:port-number:client-id-string"};
    }

    @Override
    public boolean isUndocumented() {
      return true;
    }

    @Override
    public boolean setString(String str) {
      String[] split = str.split(":");
      String hostStr = "localhost";
      String portStr = null;
      String clientId;

      if (split.length == 3) {
        hostStr = split[0];
        portStr = split[1];
        clientId = split[2];
      } else if (split.length == 2) {
        portStr = split[0];
        clientId = split[1];
      } else {
        return false;
      }

      options.setRemoteUIHost(hostStr);
      options.setClientId(clientId);

      try {
        options.setRemoteUIHostPort(Integer.parseInt(portStr));
      } catch (NumberFormatException nfe) {
        System.err.println("A port must be an integer");
        return false;
      }

      return true;
    }
  }

  /**
   * Handles the -whitelist command line flag.
   */
  protected static class ArgHandlerWhitelist extends ArgHandlerString {
    public ArgHandlerWhitelist() {
    }

    @Override
    public String getPurpose() {
      return "Allows the user to browse URLs that match the specified regexes (comma or space separated)";
    }

    @Override
    public String getTag() {
      return "-whitelist";
    }

    @Override
    public String[] getTagArgs() {
      return new String[]{"whitelist-string"};
    }

    @Override
    public boolean setString(String whitelistStr) {
      return BrowserWidgetHostChecker.whitelistRegexes(whitelistStr);
    }
  }

  /**
   * Base options for dev mode.
   */
  protected interface HostedModeBaseOptions extends PrecompileTaskOptions, OptionLogDir,
      OptionNoServer, OptionPort, OptionCodeServerPort, OptionStartupURLs, OptionRemoteUI,
      OptionBindAddress {
  }

  /**
   * Concrete class to implement all hosted mode base options.
   */
  @SuppressWarnings("serial")
  protected static class HostedModeBaseOptionsImpl extends PrecompileTaskOptionsImpl implements
      HostedModeBaseOptions {

    private String bindAddress;
    private int codeServerPort;
    private String connectAddress;
    private boolean isNoServer;
    private File logDir;
    private int port;
    private String remoteUIClientId;
    private String remoteUIHost;
    private int remoteUIHostPort;
    private final List<String> startupURLs = new ArrayList<String>();

    @Override
    public void addStartupURL(String url) {
      startupURLs.add(url);
    }

    @Override
    public boolean alsoLogToFile() {
      return logDir != null;
    }

    @Override
    public String getBindAddress() {
      return bindAddress;
    }

    @Override
    public String getClientId() {
      return remoteUIClientId;
    }

    @Override
    public int getCodeServerPort() {
      return codeServerPort;
    }

    @Override
    public String getConnectAddress() {
      return connectAddress;
    }

    @Override
    public File getLogDir() {
      return logDir;
    }

    @Override
    public File getLogFile(String sublog) {
      if (logDir == null) {
        return null;
      }
      return new File(logDir, sublog);
    }

    @Override
    public int getPort() {
      return port;
    }

    @Override
    public String getRemoteUIHost() {
      return remoteUIHost;
    }

    @Override
    public int getRemoteUIHostPort() {
      return remoteUIHostPort;
    }

    @Override
    public List<String> getStartupURLs() {
      return Collections.unmodifiableList(startupURLs);
    }

    @Override
    public boolean isNoServer() {
      return isNoServer;
    }

    @Override
    public void setBindAddress(String bindAddress) {
      this.bindAddress = bindAddress;
    }

    @Override
    public void setClientId(String clientId) {
      this.remoteUIClientId = clientId;
    }

    @Override
    public void setCodeServerPort(int port) {
      codeServerPort = port;
    }

    @Override
    public void setConnectAddress(String connectAddress) {
      this.connectAddress = connectAddress;
    }

    @Override
    public void setLogFile(String filename) {
      logDir = new File(filename);
    }

    @Override
    public void setNoServer(boolean isNoServer) {
      this.isNoServer = isNoServer;
    }

    @Override
    public void setPort(int port) {
      this.port = port;
    }

    @Override
    public void setRemoteUIHost(String remoteUIHost) {
      this.remoteUIHost = remoteUIHost;
    }

    @Override
    public void setRemoteUIHostPort(int remoteUIHostPort) {
      this.remoteUIHostPort = remoteUIHostPort;
    }

    @Override
    public boolean useRemoteUI() {
      return remoteUIHost != null;
    }
  }

  /**
   * Controls what local address to bind to.
   */
  protected interface OptionBindAddress {
    String getBindAddress();

    String getConnectAddress();

    void setBindAddress(String bindAddress);

    void setConnectAddress(String connectAddress);
  }

  /**
   * Controls what port the code server listens on.
   */
  protected interface OptionCodeServerPort {
    int getCodeServerPort();

    void setCodeServerPort(int codeServerPort);
  }

  /**
   * Controls whether and where to log data to file.
   *
   */
  protected interface OptionLogDir {
    boolean alsoLogToFile();

    File getLogDir();

    File getLogFile(String subfile);

    void setLogFile(String filename);
  }

  /**
   * Controls whether to run a server or not.
   *
   */
  protected interface OptionNoServer {
    boolean isNoServer();

    void setNoServer(boolean isNoServer);
  }

  /**
   * Controls what port to use.
   *
   */
  protected interface OptionPort {
    int getPort();

    void setPort(int port);
  }

  /**
   * Controls the UI that should be used to display the dev mode server's data.
   */
  protected interface OptionRemoteUI {
    String getClientId();

    String getRemoteUIHost();

    int getRemoteUIHostPort();

    void setClientId(String clientId);

    void setRemoteUIHost(String remoteUIHost);

    void setRemoteUIHostPort(int remoteUIHostPort);

    boolean useRemoteUI();
  }

  /**
   * Controls the startup URLs.
   */
  protected interface OptionStartupURLs {
    void addStartupURL(String url);

    List<String> getStartupURLs();
  }

  /**
   * The base dev mode argument processor.
   */
  protected abstract static class ArgProcessor extends ArgProcessorBase {
    public ArgProcessor(HostedModeBaseOptions options, boolean forceServer) {
      if (!forceServer) {
        registerHandler(new ArgHandlerNoServerFlag(options));
      }
      registerHandler(new ArgHandlerPort(options));
      registerHandler(new ArgHandlerWhitelist());
      registerHandler(new ArgHandlerBlacklist());
      registerHandler(new ArgHandlerEnableGeneratorResultCaching());
      registerHandler(new ArgHandlerLogDir(options));
      registerHandler(new ArgHandlerLogLevel(options));
      registerHandler(new ArgHandlerGenDir(options));
      registerHandler(new ArgHandlerBindAddress(options));
      registerHandler(new ArgHandlerCodeServerPort(options));
      registerHandler(new ArgHandlerRemoteUI(options));
    }
  }

  private static final boolean generatorResultCachingDisabled =
      (System.getProperty("gwt.disableGeneratorResultCaching") != null);

  private static final Random RNG = new Random();

  public static String normalizeURL(String unknownUrlText, boolean isHttps, int port, String host) {
    if (unknownUrlText.contains("://")) {
      // Assume it's a full url.
      return unknownUrlText;
    }

    // Assume it's a trailing url path.
    if (unknownUrlText.length() > 0 && unknownUrlText.charAt(0) == '/') {
      unknownUrlText = unknownUrlText.substring(1);
    }

    String protocol = "http";
    String portString = ":" + port;
    if (isHttps) {
      protocol += "s";
      if (port == 443) {
        portString = "";
      }
    } else if (port == 80) {
      portString = "";
    }

    return protocol + "://" + host + portString + "/" + unknownUrlText;
  }

  /**
   * Produce a random string that has low probability of collisions.
   *
   * <p>
   * In this case, we use 16 characters, each drawn from a pool of 94, so the
   * number of possible values is 94^16, leading to an expected number of values
   * used before a collision occurs as sqrt(pi/2) * 94^8 (treated the same as a
   * birthday attack), or a little under 10^16.
   *
   * <p>
   * This algorithm is also implemented in hosted.html, though it is not
   * technically important that they match.
   *
   * @return a random string
   */
  protected static String randomString() {
    StringBuilder buf = new StringBuilder(16);
    for (int i = 0; i < 16; ++i) {
      buf.append((char) RNG.nextInt('~' - '!' + 1) + '!');
    }
    return buf.toString();
  }

  protected TreeLogger.Type baseLogLevelForUI = null;

  protected String bindAddress;

  protected int codeServerPort;

  protected String connectAddress;

  protected boolean isHttps;

  protected BrowserListener listener;

  protected final HostedModeBaseOptions options;

  protected final CompilerContext.Builder compilerContextBuilder = new CompilerContext.Builder();

  protected CompilerContext compilerContext;

  protected DevModeUI ui = null;

  private final Semaphore blockUntilDone = new Semaphore(0);

  private BrowserWidgetHost browserHost = new UiBrowserWidgetHostImpl();

  private boolean headlessMode = false;

  private Map<String, RebindCache> rebindCaches = null;

  private boolean started;

  private TreeLogger topLogger;

  public DevModeBase() {
    // Set any platform specific system properties.
    BootStrapPlatform.initHostedMode();
    BootStrapPlatform.applyPlatformHacks();
    compilerContext = compilerContextBuilder.build();
    options = createOptions();
  }

  public final void addStartupURL(String url) {
    options.addStartupURL(url);
  }

  /**
   * Gets the base log level recommended by the UI for INFO-level messages. This
   * method can only be called once {@link #createUI()} has been called. Please
   * do not depend on this method, as it is subject to change.
   *
   * @return the log level to use for INFO-level messages
   */
  public TreeLogger.Type getBaseLogLevelForUI() {
    if (baseLogLevelForUI == null) {
      throw new IllegalStateException("The ui must be created before calling this method.");
    }

    return baseLogLevelForUI;
  }

  public final int getPort() {
    return options.getPort();
  }

  public TreeLogger getTopLogger() {
    return topLogger;
  }

  /**
   * Callback for the UI to indicate it is done.
   */
  @Override
  public void onDone() {
    setDone();
  }

  /**
   * Sets up all the major aspects of running the shell graphically, including
   * creating the main window and optionally starting an embedded web server.
   */
  public final void run() {
    try {
      // Eager AWT init for OS X to ensure safe coexistence with SWT.
      BootStrapPlatform.initGui();

      boolean success = startUp();

      // The web server is running now, so launch browsers for startup urls.
      ui.moduleLoadComplete(success);

      blockUntilDone.acquire();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      shutDown();
    }
  }

  public final void setPort(int port) {
    options.setPort(port);
  }

  public final void setRunTomcat(boolean run) {
    options.setNoServer(!run);
  }

  /**
   * Derived classes can override to lengthen ping delay.
   */
  protected long checkForUpdatesInterval() {
    return CheckForUpdates.ONE_MINUTE;
  }

  protected abstract HostedModeBaseOptions createOptions();

  /**
   * Creates an instance of ShellModuleSpaceHost (or a derived class) using the
   * specified constituent parts. This method is made to be overridden for
   * subclasses that need to change the behavior of ShellModuleSpaceHost.
   *
   * @param logger TreeLogger to use
   * @param compilationState
   * @param moduleDef
   * @return ShellModuleSpaceHost instance
   */
  protected final ShellModuleSpaceHost doCreateShellModuleSpaceHost(TreeLogger logger,
      CompilationState compilationState, ModuleDef moduleDef) throws UnableToCompleteException {
    ArtifactAcceptor artifactAcceptor = createArtifactAcceptor(logger, moduleDef);
    return new ShellModuleSpaceHost(logger, compilationState, moduleDef, options.getGenDir(),
        artifactAcceptor, getRebindCache(moduleDef.getName()));
  }

  protected abstract void doShutDownServer();

  /**
   * Perform any slower startup tasks, such as loading modules. This is separate
   * from {@link #doStartup()} so that the UI can be updated as soon as possible
   * and the web server can be started earlier.
   *
   * @return false if startup failed
   */
  protected boolean doSlowStartup() {
    // do nothing by default
    return true;
  }

  protected abstract boolean doStartup();

  /**
   * Perform any startup tasks, including initializing the UI (if any) and the
   * logger, updates checker, and the development mode code server.
   *
   * <p>
   * Subclasses that override this method should be careful what facilities are
   * used before the super implementation is called.
   *
   * @return true if startup was successful
   */
  protected boolean doStartup(File persistentCacheDir) {
    bindAddress = options.getBindAddress();
    connectAddress = options.getConnectAddress();

    // Create the main app window.
    ui.initialize(options.getLogLevel());
    topLogger = ui.getTopLogger();

    CompilationStateBuilder.init(getTopLogger(), persistentCacheDir);

    // Set done callback
    ui.setCallback(DoneEvent.getType(), this);

    // Check for updates
    if (!options.isUpdateCheckDisabled()) {
      final TreeLogger logger = getTopLogger();
      final CheckForUpdates updateChecker = CheckForUpdates.createUpdateChecker(logger);
      if (updateChecker != null) {
        Thread checkerThread = new Thread("GWT Update Checker") {
          @Override
          public void run() {
            CheckForUpdates.logUpdateAvailable(logger, updateChecker
                .check(checkForUpdatesInterval()));
          }
        };
        checkerThread.setDaemon(true);
        checkerThread.start();
      }
    }

    // Accept connections from OOPHM clients
    ensureCodeServerListener();

    return true;
  }

  protected abstract int doStartUpServer();

  protected void ensureCodeServerListener() {
    if (listener == null) {
      codeServerPort = options.getCodeServerPort();
      listener =
          new BrowserListener(getTopLogger(), bindAddress, codeServerPort, new OophmSessionHandler(
              getTopLogger(), browserHost));
      listener.start();
      try {
        // save the port we actually used if it was auto
        codeServerPort = listener.getSocketPort();
      } catch (UnableToCompleteException e) {
        // ignore errors listening, we will catch them later
      }
    }
  }

  protected String getHost() {
    return connectAddress;
  }

  /**
   * Add any plausible HTML files which might be used as startup URLs. Found
   * URLs should be added to {@code options.addStartupUrl(url)}.
   */
  protected void inferStartupUrls() {
    // do nothing by default
  }

  /**
   * By default we will open the application window.
   *
   * @return true if we are running in headless mode
   */
  protected final boolean isHeadless() {
    return headlessMode;
  }

  /**
   * Perform an initial hosted mode link, without overwriting newer or
   * unmodified files in the output folder.
   *
   * @param logger the logger to use
   * @param module the module to link
   * @throws UnableToCompleteException
   */
  protected final StandardLinkerContext link(TreeLogger logger, ModuleDef module)
      throws UnableToCompleteException {
    TreeLogger linkLogger =
        logger.branch(TreeLogger.DEBUG, "Linking module '" + module.getName() + "'");

    // Create a new active linker stack for the fresh link.
    StandardLinkerContext linkerStack = new StandardLinkerContext(linkLogger, module, options);
    ArtifactSet artifacts = linkerStack.getArtifactsForPublicResources(logger, module);
    artifacts = linkerStack.invokeLegacyLinkers(linkLogger, artifacts);
    artifacts = linkerStack.invokeFinalLink(linkLogger, artifacts);
    produceOutput(linkLogger, linkerStack, artifacts, module, false);
    return linkerStack;
  }

  /**
   * Load a module.
   *
   * @param logger TreeLogger to use
   * @param moduleName name of the module to load
   * @param refresh if <code>true</code>, refresh the module from disk
   *
   * @return the loaded module
   * @throws UnableToCompleteException
   */
  protected ModuleDef loadModule(TreeLogger logger, String moduleName, boolean refresh)
      throws UnableToCompleteException {
    ModuleDef moduleDef =
        ModuleDefLoader.loadFromClassPath(logger, compilerContext, moduleName, refresh, true);
    compilerContext = compilerContextBuilder.module(moduleDef).build();
    assert (moduleDef != null) : "Required module state is absent";
    return moduleDef;
  }

  protected URL processUrl(String url) throws UnableToCompleteException {
    /*
     * TODO(jat): properly support launching arbitrary browsers -- need some UI
     * API tweaks to support that.
     */
    URL parsedUrl = null;
    try {
      parsedUrl = new URL(url);
      String path = parsedUrl.getPath();
      String query = parsedUrl.getQuery();
      String hash = parsedUrl.getRef();
      String hostedParam =
          BrowserListener.getDevModeURLParams(connectAddress, listener.getSocketPort());
      if (query == null) {
        query = hostedParam;
      } else {
        query += '&' + hostedParam;
      }
      path += '?' + query;
      if (hash != null) {
        path += '#' + hash;
      }
      parsedUrl = new URL(parsedUrl.getProtocol(), parsedUrl.getHost(), parsedUrl.getPort(), path);
      url = parsedUrl.toExternalForm();
    } catch (MalformedURLException e) {
      getTopLogger().log(TreeLogger.ERROR, "Invalid URL " + url, e);
      throw new UnableToCompleteException();
    }
    return parsedUrl;
  }

  protected abstract void produceOutput(TreeLogger logger, StandardLinkerContext linkerStack,
      ArtifactSet artifacts, ModuleDef module, boolean isRelink) throws UnableToCompleteException;

  protected final void setDone() {
    blockUntilDone.release();
  }

  protected final void setHeadless(boolean headlessMode) {
    this.headlessMode = headlessMode;
  }

  protected final void shutDown() {
    if (options.isNoServer()) {
      return;
    }
    doShutDownServer();
  }

  protected final boolean startUp() {
    if (started) {
      throw new IllegalStateException("Startup code has already been run");
    }

    Event startupEvent = SpeedTracerLogger.start(DevModeEventType.STARTUP);
    try {
      // See if there was a UI specified by command-line args
      ui = createUI();

      started = true;

      if (!doStartup()) {
        /*
         * TODO (amitmanjhi): Adding this redundant logging to narrow down a
         * failure. Remove soon.
         */
        getTopLogger().log(TreeLogger.ERROR, "shell failed in doStartup method");
        return false;
      }

      if (!options.isNoServer()) {
        int resultPort = doStartUpServer();
        if (resultPort < 0) {
          /*
           * TODO (amitmanjhi): Adding this redundant logging to narrow down a
           * failure. Remove soon.
           */
          getTopLogger().log(TreeLogger.ERROR, "shell failed in doStartupServer method");
          return false;
        }
        options.setPort(resultPort);
        getTopLogger().log(TreeLogger.TRACE, "Started web server on port " + resultPort);
      }

      if (options.getStartupURLs().isEmpty()) {
        // if no URLs were supplied, try and find plausible ones
        inferStartupUrls();
      }

      if (options.getStartupURLs().isEmpty()) {
        // TODO(jat): we could walk public resources to find plausible URLs
        // after the module(s) are loaded
        warnAboutNoStartupUrls();
      }

      setStartupUrls(getTopLogger());

      if (!doSlowStartup()) {
        /*
         * TODO (amitmanjhi): Adding this redundant logging to narrow down a
         * failure. Remove soon.
         */
        getTopLogger().log(TreeLogger.ERROR, "shell failed in doSlowStartup method");
        return false;
      }

      return true;
    } finally {
      startupEvent.end();
    }
  }

  /**
   * Log a warning explaining that no startup URLs were specified and no
   * plausible startup URLs were found.
   */
  protected abstract void warnAboutNoStartupUrls();

  private ArtifactAcceptor createArtifactAcceptor(TreeLogger logger, final ModuleDef module)
      throws UnableToCompleteException {
    final StandardLinkerContext linkerContext = link(logger, module);
    return new ArtifactAcceptor() {
      @Override
      public void accept(TreeLogger relinkLogger, ArtifactSet newArtifacts)
          throws UnableToCompleteException {
        relink(relinkLogger, linkerContext, module, newArtifacts);
      }
    };
  }

  /**
   * Create the UI and set the base log level for the UI.
   */
  private DevModeUI createUI() {
    DevModeUI newUI = null;

    Event createUIEvent = SpeedTracerLogger.start(DevModeEventType.CREATE_UI);

    if (headlessMode) {
      newUI = new HeadlessUI(options);
    } else {
      if (options.useRemoteUI()) {
        try {
          newUI =
              new RemoteUI(options.getRemoteUIHost(), options.getRemoteUIHostPort(), options
                  .getClientId());
          baseLogLevelForUI = TreeLogger.Type.TRACE;
        } catch (Throwable t) {
          System.err.println("Could not connect to remote UI listening at "
              + options.getRemoteUIHost() + ":" + options.getRemoteUIHostPort()
              + ". Using default UI instead.");
        }
      }
    }

    if (newUI == null) {
      newUI = new SwingUI(options);
    }

    if (baseLogLevelForUI == null) {
      baseLogLevelForUI = TreeLogger.Type.INFO;
    }

    createUIEvent.end();
    return newUI;
  }

  private RebindCache getRebindCache(String moduleName) {

    if (generatorResultCachingDisabled) {
      return null;
    }

    if (rebindCaches == null) {
      rebindCaches = new HashMap<String, RebindCache>();
    }

    RebindCache cache = rebindCaches.get(moduleName);
    if (cache == null) {
      cache = new RebindCache();
      rebindCaches.put(moduleName, cache);
    }
    return cache;
  }

  /**
   * Perform hosted mode relink when new artifacts are generated, without
   * overwriting newer or unmodified files in the output folder.
   *
   * @param logger the logger to use
   * @param module the module to link
   * @param newlyGeneratedArtifacts the set of new artifacts
   * @throws UnableToCompleteException
   */
  private void relink(TreeLogger logger, StandardLinkerContext linkerContext, ModuleDef module,
      ArtifactSet newlyGeneratedArtifacts) throws UnableToCompleteException {
    TreeLogger linkLogger =
        logger.branch(TreeLogger.DEBUG, "Relinking module '" + module.getName() + "'");

    ArtifactSet artifacts = linkerContext.invokeRelink(linkLogger, newlyGeneratedArtifacts);
    produceOutput(linkLogger, linkerContext, artifacts, module, true);
  }

  /**
   * Set the set of startup URLs. This is done before launching to allow the UI
   * to better present the options to the user, but note that the UI should not
   * attempt to launch the URLs until
   * {@link DevModeUI#moduleLoadComplete(boolean)} is called, and should not
   * automatically launch any URLs if they
   *
   * @param logger TreeLogger instance to use
   */
  private void setStartupUrls(final TreeLogger logger) {
    ensureCodeServerListener();
    Map<String, URL> startupUrls = new HashMap<String, URL>();
    for (String prenormalized : options.getStartupURLs()) {
      String startupURL = normalizeURL(prenormalized, isHttps, getPort(), getHost());
      logger.log(TreeLogger.DEBUG, "URL " + prenormalized + " normalized as " + startupURL, null);
      try {
        URL url = processUrl(startupURL);
        startupUrls.put(prenormalized, url);
      } catch (UnableToCompleteException e) {
        logger.log(TreeLogger.ERROR, "Unable to process startup URL " + startupURL, null);
      }
    }
    ui.setStartupUrls(startupUrls);
  }
}
