/*
 * Copyright 2014 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.shell;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
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.DevMode.HostedModeOptions;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.util.arg.OptionMethodNameDisplayMode;
import com.google.gwt.thirdparty.guava.common.base.Stopwatch;
import com.google.gwt.thirdparty.guava.common.collect.ListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.Lists;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * Starts a superdev-mode codeserver.
 */
public class SuperDevListener implements CodeServerListener {

  private final TreeLogger logger;
  private final int codeServerPort;
  private List<String> codeServerArgs;

  /**
   * Listens for new connections from browsers.
   */
  public SuperDevListener(TreeLogger treeLogger, HostedModeOptions options) {
    this.logger = treeLogger;
    this.codeServerPort = chooseCodeServerPort(treeLogger, options);

    // This directory must exist when the Code Server starts.
    ensureModuleBaseDir(options);

    codeServerArgs = makeCodeServerArgs(options, codeServerPort);
  }

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

  @Override
  public URL makeStartupUrl(String url) throws UnableToCompleteException {
    try {
      return new URL(url);
    } catch (MalformedURLException e) {
      logger.log(TreeLogger.ERROR, "Invalid URL " + url, e);
      throw new UnableToCompleteException();
    }
  }

  @Override
  public void writeCompilerOutput(StandardLinkerContext linkerStack, ArtifactSet artifacts,
      ModuleDef module, boolean isRelink) throws UnableToCompleteException {
    // The code server will do this.
  }

  @Override
  public void setIgnoreRemoteDeath(boolean b) {
  }

  @Override
  public void start() {
    try {
      Stopwatch watch = Stopwatch.createStarted();
      logger.log(Type.INFO, "Running CodeServer with parameters: " + codeServerArgs);
      runCodeServer(codeServerArgs.toArray(new String[0]));
      logger.log(Type.INFO, "Code server started in " + watch + " ms");
    } catch (Exception e) {
      logger.log(Type.INFO, "Unable to start Code server");
      throw new RuntimeException(e);
    }
  }

  private void runCodeServer(String[] mainArgs) throws Exception {
    // Using reflection so as we don't create a circular dependency between
    // dev.jar && codeserver.jar
    Method mainMethod;
    try {
      Class<?> clazz = Class.forName("com.google.gwt.dev.codeserver.CodeServer");
      mainMethod = clazz.getMethod("main", String[].class);
    } catch (ClassNotFoundException e) {
      logger.log(TreeLogger.ERROR, "Unable to find main() method for Super Dev Mode "
          + "code server. Hint: verify that gwt-codeserver.jar is in your classpath.");
      throw e;
    }

    mainMethod.invoke(null, new Object[] {mainArgs});
  }

  private static int chooseCodeServerPort(TreeLogger logger, HostedModeOptions options) {
    int port = options.getCodeServerPort();
    if (port == 0) {
      // Automatically choose an unused port.
      try {
        ServerSocket serverSocket = new ServerSocket(0);
        port = serverSocket.getLocalPort();
        serverSocket.close();
        return port;
      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Unable to get an unnused port.");
        throw new RuntimeException(e);
      }
    } else if (port < 0 || port == 9997) {
      // 9997 is the default non-SuperDevMode port from DevModeBase. TODO: use constant.
      return 9876; // Default Super Dev Mode port
    } else {
      return port; // User-specified port
    }
  }

  private static void ensureModuleBaseDir(HostedModeOptions options) {
    File dir = options.getModuleBaseDir();
    if (!dir.isDirectory()) {
      dir.mkdirs();
      if (!dir.isDirectory()) {
        throw new RuntimeException("unable to create module base directory: " +
            dir.getAbsolutePath());
      }
    }
  }

  private static List<String> makeCodeServerArgs(HostedModeOptions options, int port) {
    List<String> args = new ArrayList<String>();
    args.add("-noprecompile");
    args.add("-port");
    args.add(String.valueOf(port));
    args.add("-sourceLevel");
    args.add(String.valueOf(options.getSourceLevel()));
    if (options.getBindAddress() != null) {
      args.add("-bindAddress");
      args.add(options.getBindAddress());
    }
    if (options.getWorkDir() != null) {
      args.add("-workDir");
      args.add(String.valueOf(options.getWorkDir()));
    }
    args.add("-launcherDir");
    args.add(options.getModuleBaseDir().getAbsolutePath());
    if (options.getLogLevel() != null) {
      args.add("-logLevel");
      args.add(String.valueOf(options.getLogLevel()));
    }
    if (options.shouldGenerateJsInteropExports()) {
      args.add("-generateJsInteropExports");
    }
    for (String regex : options.getJsInteropExportFilter().getValues()) {
      if (regex.startsWith("-")) {
        args.add("-excludeJsInteropExports");
        args.add(regex.substring(1));
      } else {
        args.add("-includeJsInteropExports");
        args.add(regex);
      }
    }
    if (!options.isIncrementalCompileEnabled()) {
      args.add("-noincremental");
    }
    if (options.getMethodNameDisplayMode() != OptionMethodNameDisplayMode.Mode.NONE) {
      args.add("-XmethodNameDisplayMode");
      args.add(options.getMethodNameDisplayMode().name());
    }

    args.add("-style");
    args.add(options.getOutput().name());

    if (options.isStrict()) {
      args.add("-strict");
    }

    if (options.getProperties().size() > 0) {
      args.addAll(makeSetPropertyArgs(options.getProperties()));
    }
    for (String mod : options.getModuleNames()) {
      args.add(mod);
    }
    return args;
  }

  private static List<String> makeSetPropertyArgs(
      ListMultimap<String, String> properties) {
    List<String> propertyArgs = Lists.newArrayList();
    for (String propertyName : properties.keySet()) {
      propertyArgs.add("-setProperty");
      StringBuilder nameValues = new StringBuilder(propertyName + "=");
      for (String propertyValue : properties.get(propertyName)) {
        nameValues.append(propertyValue + ",");
      }
      propertyArgs.add(nameValues.substring(0, nameValues.length() - 1));
    }
    return propertyArgs;
  }
}
