/*
 * 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.jjs.JsOutputOption;
import com.google.gwt.dev.util.arg.ArgHandlerBindAddress;
import com.google.gwt.dev.util.arg.ArgHandlerClosureFormattedOutput;
import com.google.gwt.dev.util.arg.ArgHandlerGenerateJsInteropExports;
import com.google.gwt.dev.util.arg.ArgHandlerIncrementalCompile;
import com.google.gwt.dev.util.arg.ArgHandlerLogLevel;
import com.google.gwt.dev.util.arg.ArgHandlerMethodNameDisplayMode;
import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle;
import com.google.gwt.dev.util.arg.ArgHandlerSetProperties;
import com.google.gwt.dev.util.arg.ArgHandlerSourceLevel;
import com.google.gwt.dev.util.arg.OptionBindAddress;
import com.google.gwt.dev.util.arg.OptionClosureFormattedOutput;
import com.google.gwt.dev.util.arg.OptionGenerateJsInteropExports;
import com.google.gwt.dev.util.arg.OptionIncrementalCompile;
import com.google.gwt.dev.util.arg.OptionLogLevel;
import com.google.gwt.dev.util.arg.OptionMethodNameDisplayMode;
import com.google.gwt.dev.util.arg.OptionScriptStyle;
import com.google.gwt.dev.util.arg.OptionSetProperties;
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.thirdparty.guava.common.collect.LinkedListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ListMultimap;
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 java.io.File;
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 = ArgHandlerBindAddress.DEFAULT_BIND_ADDRESS;
  private String preferredHost = ArgHandlerBindAddress.DEFAULT_BIND_ADDRESS;
  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 int compileTestRecompiles = 0;
  private boolean generateJsInteropExports = false;
  private OptionMethodNameDisplayMode.Mode methodNameDisplayMode =
      OptionMethodNameDisplayMode.Mode.NONE;
  private boolean closureFormattedOutput = false;
  // Incremental superdevmod has different defaults than devmode and regular superdevmode; we use
  // null here means not set by the user (and the right default is computed by getOutput().
  private JsOutputOption output = null;

  private final ListMultimap<String, String> properties = LinkedListMultimap.create();

  /**
   * 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;
  }

  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;
  }

  boolean shouldGenerateJsInteropExports() {
    return generateJsInteropExports;
  }

  JsOutputOption getOutput() {
    if (output == null) {
      return isIncrementalCompileEnabled() ? JsOutputOption.OBFUSCATED : JsOutputOption.PRETTY;
    }
    return output;
  }

  ListMultimap<String, String> getProperties() {
    return properties;
  }

  public boolean isClosureFormattedOutput() {
    return closureFormattedOutput;
  }

  private class ArgProcessor extends ArgProcessorBase {

    public ArgProcessor() {
      registerHandler(new AllowMissingSourceDirFlag());
      registerHandler(new CompileTestFlag());
      registerHandler(new CompileTestRecompilesFlag());
      registerHandler(new FailOnErrorFlag());
      registerHandler(new ModuleNameArgument());
      registerHandler(new NoPrecompileFlag());
      registerHandler(new PortFlag());
      registerHandler(new SourceFlag());
      registerHandler(new WorkDirFlag());
      registerHandler(new LauncherDir());
      registerHandler(new ArgHandlerBindAddress(new OptionBindAddress() {
        @Override
        public String getBindAddress() {
          return Options.this.bindAddress;
        }

        @Override
        public String getConnectAddress() {
          return Options.this.preferredHost;
        }

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

        @Override
        public void setConnectAddress(String connectAddress) {
          Options.this.preferredHost = connectAddress;
        }
      }));
      registerHandler(new ArgHandlerScriptStyle(new OptionScriptStyle() {
        @Override
        public JsOutputOption getOutput() {
          return Options.this.output;
        }

        @Override
        public void setOutput(JsOutputOption output) {
          Options.this.output = output;
        }
      }));
      registerHandler(new ArgHandlerSetProperties(new OptionSetProperties() {

          @Override
        public void setPropertyValues(String name, Iterable<String> values) {
          properties.replaceValues(name, values);
        }

          @Override
        public ListMultimap<String, String> getProperties() {
          return properties;
        }

      }));
      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 ArgHandlerGenerateJsInteropExports(new OptionGenerateJsInteropExports() {
        @Override
        public boolean shouldGenerateJsInteropExports() {
          return Options.this.generateJsInteropExports;
        }

        @Override
        public void setGenerateJsInteropExports(boolean generateExports) {
          Options.this.generateJsInteropExports = generateExports;
        }
      }));
      registerHandler(new ArgHandlerMethodNameDisplayMode(new OptionMethodNameDisplayMode() {
        @Override
        public OptionMethodNameDisplayMode.Mode getMethodNameDisplayMode() {
          return Options.this.methodNameDisplayMode;
        }

        @Override
        public void setMethodNameDisplayMode(Mode mode) {
          Options.this.methodNameDisplayMode = mode;
        }
      }));
      registerHandler(new ArgHandlerClosureFormattedOutput(new OptionClosureFormattedOutput() {
        @Override
        public boolean isClosureCompilerFormatEnabled() {
          return Options.this.closureFormattedOutput;
        }

        @Override
        public void setClosureCompilerFormatEnabled(boolean enabled) {
          Options.this.closureFormattedOutput = enabled;
        }
      }));
    }

    @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 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 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.exists() && !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;
    }
  }

  public OptionMethodNameDisplayMode.Mode getMethodNameDisplayMode() {
    return methodNameDisplayMode;
  }
}
