/*
 * 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 " + regex.substring(1));
      } else {
        args.add("-includeJsInteropExports " + 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;
  }
}
