/*
 * Copyright 2011 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.codeserver;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.ArgProcessorBase;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.util.arg.ArgHandlerIncrementalCompile;
import com.google.gwt.dev.util.arg.ArgHandlerJsInteropMode;
import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
import com.google.gwt.dev.util.arg.ArgHandlerSourceLevel;
import com.google.gwt.dev.util.arg.JsInteropMode;
import com.google.gwt.dev.util.arg.OptionIncrementalCompile;
import com.google.gwt.dev.util.arg.OptionJsInteropMode;
import com.google.gwt.dev.util.arg.OptionLogLevel;
import com.google.gwt.dev.util.arg.OptionSourceLevel;
import com.google.gwt.dev.util.arg.SourceLevel;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableList;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.util.tools.ArgHandler;
import com.google.gwt.util.tools.ArgHandlerDir;
import com.google.gwt.util.tools.ArgHandlerExtra;
import com.google.gwt.util.tools.ArgHandlerFlag;
import com.google.gwt.util.tools.ArgHandlerInt;
import com.google.gwt.util.tools.ArgHandlerString;

import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Defines the command-line options for the {@link CodeServer CodeServer's} main() method.
 *
 * <p>These flags are EXPERIMENTAL and subject to change.</p>
 */
public class Options {
  private ImmutableList<String> args;
  private Set<String> tags = new LinkedHashSet<String>();

  private boolean incremental = true;
  private boolean noPrecompile = false;
  private boolean isCompileTest = false;
  private File workDir;
  private File launcherDir;
  private final List<String> moduleNames = new ArrayList<String>();
  private boolean allowMissingSourceDir = false;
  private final List<File> sourcePath = new ArrayList<File>();
  private String bindAddress = "127.0.0.1";
  private String preferredHost = "localhost";
  private int port = 9876;

  private RecompileListener recompileListener = RecompileListener.NONE;
  private JobChangeListener jobChangeListener = JobChangeListener.NONE;

  private TreeLogger.Type logLevel = TreeLogger.Type.INFO;
  // Use the same default as the GWT compiler.
  private SourceLevel sourceLevel = SourceLevel.DEFAULT_SOURCE_LEVEL;
  private boolean failOnError = false;
  private boolean strictResources = false;
  private int compileTestRecompiles = 0;
  private JsInteropMode jsInteropMode = JsInteropMode.NONE;

  /**
   * Sets each option to the appropriate value, based on command-line arguments.
   * If there is an error, prints error messages and/or usage to System.err.
   * @return true if the arguments were parsed successfully.
   */
  public boolean parseArgs(String[] args) {
    if (this.args != null) {
      throw new IllegalStateException("parseArgs may only be called once");
    }
    this.args = ImmutableList.copyOf(Arrays.asList(args));

    boolean ok = new ArgProcessor().processArgs(args);
    if (!ok) {
      return false;
    }

    if (isCompileTest && noPrecompile) {
      System.err.println("Usage: -noprecompile and -compiletest are incompatible");
      return false;
    }

    if (moduleNames.isEmpty()) {
      System.err.println("Usage: at least one module must be supplied");
      return false;
    }

    if (incremental && !noPrecompile) {
      System.out.println("Turning off precompile in incremental mode.");
      noPrecompile = true;
    }

    // Set some tags automatically for migration tracking.
    if (isIncrementalCompileEnabled()) {
      addTags("incremental_on");
    } else {
      addTags("incremental_off");
    }

    if (getNoPrecompile()) {
      addTags("precompile_off");
    } else {
      addTags("precompile_on");
    }

    return true;
  }

  /**
   * Adds some user-defined tags that will be passed through to {@link JobEvent#getTags}.
   *
   * <p>A tag may not be null, contain whitespace, or be more than 100 characters.
   * If a tag was already added, it won't be added again.
   *
   * <p>This method may be called more than once, but compile jobs that are already running
   * will not have the new tags.
   */
  public synchronized void addTags(String... tags) {
    this.tags.addAll(JobEvent.checkTags(Arrays.asList(tags)));
  }

  /**
   * Returns the arguments passed to {@link #parseArgs}.
   */
  ImmutableList<String> getArgs() {
    return args;
  }

  /**
   * Returns the tags passed to {@link #addTags}.
   */
  synchronized Set<String> getTags() {
    return ImmutableSet.copyOf(tags);
  }

  /**
   * A Java application that embeds Super Dev Mode can use this hook to find out
   * when compiles start and end.
   *
   * @deprecated replaced by {@link #setJobChangeListener}
   */
  @Deprecated
  public void setRecompileListener(RecompileListener listener) {
    this.recompileListener = listener == null ? RecompileListener.NONE : listener;
  }

  RecompileListener getRecompileListener() {
    return recompileListener;
  }

  /**
   * A Java application that embeds Super Dev Mode can use this hook to find out
   * when compile jobs change state.
   *
   * <p>Replaces {@link #setRecompileListener}
   */
  public void setJobChangeListener(JobChangeListener listener) {
    this.jobChangeListener = listener == null ? JobChangeListener.NONE : listener;
  }

  JobChangeListener getJobChangeListener() {
    return jobChangeListener;
  }

  /**
   * The top level of the directory tree where the code server keeps compiler output.
   */
  File getWorkDir() {
    return workDir;
  }

  /**
   * A directory where each module's files for launching Super Dev Mode should be written,
   * or null if not supplied.
   * (For example, nocache.js and public resource files will go here.)
   */
  File getLauncherDir() {
    return launcherDir;
  }

  /**
   * The names of the module that will be compiled (along with all its dependencies).
   */
  List<String> getModuleNames() {
    return moduleNames;
  }

  /**
   * Whether the codeServer should allow missing source directories.
   */
  boolean shouldAllowMissingSourceDir() {
    return allowMissingSourceDir;
  }

  /**
   * Compiles faster by creating a JavaScript file per class. Can't be turned on at the same time as
   * shouldCompileIncremental().
   */
  boolean isIncrementalCompileEnabled() {
    return incremental;
  }

  /**
   * Whether the codeServer should start without precompiling modules.
   */
  boolean getNoPrecompile() {
    return noPrecompile;
  }

  /**
   * The tree logger level.
   */
  TreeLogger.Type getLogLevel() {
    return logLevel;
  }

  /**
   * Java source level compatibility,
   */
  SourceLevel getSourceLevel() {
    return sourceLevel;
  }

  /**
   * If true, just compile the modules, then exit.
   */
  boolean isCompileTest() {
    return isCompileTest;
  }

  /**
   * The IP address where the code server should listen.
   */
  String getBindAddress() {
    return bindAddress;
  }

  int getCompileTestRecompiles() {
    return compileTestRecompiles;
  }

  /**
   * The hostname to put in a URL pointing to the code server.
   */
  String getPreferredHost() {
    return preferredHost;
  }

  /**
   * The port where the code server will listen for HTTP requests.
   */
  int getPort() {
    return port;
  }

  /**
   * Whether to implicitly import client and public directories when no explicit imports exist.
   */
  boolean enforceStrictResources() {
    return strictResources;
  }

  List<File> getSourcePath() {
    return sourcePath;
  }

  /**
   * If true, run the compiler in "strict" mode, which fails the compile if any Java file
   * cannot be compiled, whether or not it is used.
   */
  boolean isFailOnError() {
    return failOnError;
  }

  JsInteropMode getJsInteropMode() {
    return jsInteropMode;
  }

  private class ArgProcessor extends ArgProcessorBase {

    public ArgProcessor() {
      registerHandler(new AllowMissingSourceDirFlag());
      registerHandler(new BindAddressFlag());
      registerHandler(new CompileTestFlag());
      registerHandler(new CompileTestRecompilesFlag());
      registerHandler(new FailOnErrorFlag());
      registerHandler(new ModuleNameArgument());
      registerHandler(new NoPrecompileFlag());
      registerHandler(new PortFlag());
      registerHandler(new SourceFlag());
      registerHandler(new StrictResourcesFlag());
      registerHandler(new WorkDirFlag());
      registerHandler(new LauncherDir());
      registerHandler(new ArgHandlerIncrementalCompile(new OptionIncrementalCompile() {
        @Override
        public boolean isIncrementalCompileEnabled() {
          return incremental;
        }

        @Override
        public void setIncrementalCompileEnabled(boolean enabled) {
          incremental = enabled;
        }
      }));
      registerHandler(new ArgHandlerSourceLevel(new OptionSourceLevel() {
        @Override
        public SourceLevel getSourceLevel() {
          return sourceLevel;
        }

        @Override
        public void setSourceLevel(SourceLevel sourceLevel) {
          Options.this.sourceLevel = sourceLevel;
        }
      }));
      registerHandler(new ArgHandlerLogLevel(new OptionLogLevel() {
        @Override
        public TreeLogger.Type getLogLevel() {
          return logLevel;
        }

        @Override
        public void setLogLevel(TreeLogger.Type logLevel) {
          Options.this.logLevel = logLevel;
        }
      }));
      registerHandler(new ArgHandlerJsInteropMode(new OptionJsInteropMode() {
        @Override
        public JsInteropMode getJsInteropMode() {
          return Options.this.jsInteropMode;
        }

        @Override
        public void setJsInteropMode(JsInteropMode mode) {
          Options.this.jsInteropMode = mode;
        }}));
    }

    @Override
    protected String getName() {
      return CodeServer.class.getName();
    }
  }

  private class NoPrecompileFlag extends ArgHandlerFlag {

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

    @Override
    public String getPurposeSnippet() {
      return "Precompile modules.";
    }

    @Override
    public boolean setFlag(boolean value) {
      noPrecompile = !value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return !noPrecompile;
    }
  }

  private class CompileTestFlag extends ArgHandlerFlag {

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

    @Override
    public String getPurposeSnippet() {
      return "Exits after compiling the modules. The exit code will be 0 if the compile succeeded.";
    }

    @Override
    public boolean setFlag(boolean value) {
      isCompileTest = value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return isCompileTest;
    }
  }

  private class CompileTestRecompilesFlag extends ArgHandlerInt {

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

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

    @Override
    public String getPurpose() {
      return "The number of times to recompile (after the first one) during a compile test.";
    }

    @Override
    public void setInt(int value) {
      compileTestRecompiles = value;
    }
  }

  private class BindAddressFlag extends ArgHandlerString {

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

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

    @Override
    public String getPurpose() {
      return "The ip address of the code server. Defaults to 127.0.0.1.";
    }

    @Override
    public boolean setString(String newValue) {
      try {
        InetAddress newBindAddress = InetAddress.getByName(newValue);
        if (newBindAddress.isAnyLocalAddress()) {
          preferredHost = InetAddress.getLocalHost().getHostName();
        } else {
          preferredHost = newValue;
        }
      } catch (UnknownHostException e) {
        System.err.println("Can't resolve bind address: " + newValue);
        return false;
      }

      // Save the original since there's no way to get it back from an InetAddress.
      bindAddress = newValue;
      return true;
    }
  }

  private class PortFlag extends ArgHandlerInt {

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

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


    @Override
    public String getPurpose() {
      return "The port where the code server will run.";
    }

    @Override
    public void setInt(int newValue) {
      port = newValue;
    }
  }

  private class WorkDirFlag extends ArgHandlerDir {

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

    @Override
    public String getPurpose() {
      return "The root of the directory tree where the code server will"
          + "write compiler output. If not supplied, a temporary directory"
          + "will be used.";
    }

    @Override
    public void setDir(File newValue) {
      workDir = newValue;
    }
  }

  private class FailOnErrorFlag extends ArgHandlerFlag {

    FailOnErrorFlag() {
      // Backward compatibility with -strict in the regular compiler.
      addTagValue("-strict", true);
    }

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

    @Override
    public boolean getDefaultValue() {
      return false;
    }

    @Override
    public String getPurposeSnippet() {
      return "Stop compiling if a module has a Java file with a compile error, even if unused.";
    }

    @Override
    public boolean setFlag(boolean value) {
      failOnError = value;
      return true;
    }
  }

  private class StrictResourcesFlag extends ArgHandlerFlag {

    public StrictResourcesFlag() {
      addTagValue("-XstrictResources", true);
    }

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

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

    @Override
    public String getPurposeSnippet() {
      return "Don't implicitly depend on \"client\" and \"public\" when "
          + "a module doesn't define any dependencies.";
    }

    @Override
    public boolean setFlag(boolean value) {
      strictResources = value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return false;
    }
  }

  private class AllowMissingSourceDirFlag extends ArgHandlerFlag {

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

    @Override
    public String getPurposeSnippet() {
      return "Allows -src flags to reference missing directories.";
    }

    @Override
    public boolean setFlag(boolean value) {
      allowMissingSourceDir = value;
      return true;
    }

    @Override
    public boolean getDefaultValue() {
      return allowMissingSourceDir;
    }
  }

  private class SourceFlag extends ArgHandler {

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

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

    @Override
    public String getPurpose() {
      return "A directory containing GWT source to be prepended to the classpath for compiling.";
    }

    @Override
    public int handle(String[] args, int startIndex) {
      if (startIndex + 1 >= args.length) {
        System.err.println(getTag() + " should be followed by the name of a directory");
        return -1;
      }

      File candidate = new File(args[startIndex + 1]);
      if (!allowMissingSourceDir && !candidate.isDirectory()) {
        System.err.println("not a directory: " + candidate);
        return -1;
      }

      sourcePath.add(candidate);
      return 1;
    }
  }

  private class LauncherDir extends ArgHandler {

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

    @Override
    public String[] getTags() {
      // add an alias since in DevMode this was "-war"
      return new String[] {getTag(), "-war"};
    }

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

    @Override
    public String getPurpose() {
      return "An output directory where files for launching Super Dev Mode will be written. "
          + "(Optional.)";
    }

    @Override
    public int handle(String[] args, int startIndex) {
      if (startIndex + 1 >= args.length) {
        System.err.println(getTag() + " should be followed by the name of a directory");
        return -1;
      }

      File candidate = new File(args[startIndex + 1]);
      if (!candidate.isDirectory()) {
        System.err.println("not a directory: " + candidate);
        return -1;
      }

      launcherDir = candidate;
      return 1;
    }
  }

  private class ModuleNameArgument extends ArgHandlerExtra {

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

    @Override
    public String getPurpose() {
      return "The GWT modules that the code server should compile. (Example: com.example.MyApp)";
    }

    @Override
    public boolean addExtraArg(String arg) {
      if (!ModuleDef.isValidModuleName(arg)) {
        System.err.println("Invalid module name: '" + arg + "'");
        return false;
      }
      moduleNames.add(arg);
      return true;
    }
  }
}
