// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler;

import com.google.common.collect.Lists;
import com.google.dart.compiler.CompilerConfiguration.ErrorFormat;
import com.google.dart.compiler.util.apache.StringUtils;

import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Options that can be specified on the command line.
 */
public class CommandLineOptions {

  /**
   * Command line options accepted by the {@link DartCompiler} entry point.
   */
  public static class CompilerOptions {

    @Option(name = "--batch", aliases = { "-batch" },
        usage = "Batch mode (for unit testing)")
    private boolean batch = false;

    @Option(name = "--error_format",
        usage = "Format errors as normal or machine")
    private String errorFormat = "";

    @Option(name = "--enable_type_checks",
        usage = "Generate runtime type checks")
    private boolean developerModeChecks = false;

    @Option(name = "--ignore-unrecognized-flags",
        usage = "Ignore unrecognized command line flags")
    private boolean ignoreUnrecognizedFlags = false;

    @Option(name = "--jvm-metrics-detail",
        usage = "Display summary (default) or\n verbose metrics")
    private String jvmMetricDetail = "summary";

    @Option(name = "--jvm-metrics-format",
        usage = "Output metrics in tabular (default)\n or pretty format")
    private String jvmMetricFormat = "tabular";

    @Option(name = "--jvm-metrics-type",
        usage = "Comma-separated list to display:\n "
        + "  all:  (default) all stat types\n "
        + "  gc:   show garbage collection stats\n "
        + "  mem:  show memory stats\n "
        + "  jit:  show jit stats")
    private String jvmMetricType = "all";

    // leave the command line flag for legacy purposes.
    @SuppressWarnings("unused")
    @Option(name = "--noincremental",
        usage = "Disable incremental compilation (default)")
    private boolean noincremental = true; // not used, just a placeholder for arg parsing

    @Option(name = "--incremental",
    usage = "Enable incremental compilation")
    private boolean incremental = false;

    @Option(name = "--work", aliases = { "-out" },
        usage = "Directory to receive compiler output\n for future incremental builds")
    private File workDirectory = new File("out");

    @Option(name = "--help", aliases = { "-?", "-help" },
        usage = "Prints this help message")
    private boolean showHelp = false;

    @Option(name = "--jvm-metrics",
        usage = "Print jvm metrics at end of compile")
    private boolean showJvmMetrics = false;

    @Option(name = "--metrics",
        usage = "Print compilation metrics")
    private boolean showMetrics = false;

    @Option(name = "--fatal-type-errors", aliases = { "-fatal-type-errors" },
        usage = "Treat type errors as fatal")
    private boolean typeErrorsAreFatal = false;

    @Option(name = "--fatal-warnings", aliases = { "-Werror" },
        usage = "Treat non-type warnings as fatal")
    private boolean warningsAreFatal = false;

    @Option(name = "--platform",
        usage = "Platform libraries to analyze (e.g. dartium, vm, dart2js, any)")
    private String platformName = PackageLibraryManager.DEFAULT_PLATFORM;

    @Option(name = "--dart-sdk",
        usage = "Path to dart sdk.  (system property com.google.dart.sdk)")
    private File dartSdkPath = PackageLibraryManager.DEFAULT_SDK_PATH;
    
    @Option(name = "--package-root",
        usage = "Root directory used for the package: scheme")
    private File packageRoot = PackageLibraryManager.DEFAULT_PACKAGE_ROOT;
    
    @Option(name = "--show-sdk-warnings", usage = "show warnings from SDK source")
    private boolean showSdkWarnings = false;
    
    @Option(name = "--source-from-ast",
        usage = "For debugging, reconstitute source code from the parsed AST.")
    private boolean showSourceFromAst = false;

    @Option(name = "--resolve-on-parse-error",
        usage = "For debugging, continue on with resolution even if there are parse errors.")
    private boolean resolveDespiteParseErrors;

    @Option(name = "--version",
        usage = "Show analyzer version")
    private boolean showVersion = false;

    @Argument
    private final List<String> sourceFiles = new ArrayList<String>();

    public String getJvmMetricOptions() {
      if (!showJvmMetrics) {
        return null;
      }
      return jvmMetricDetail + ":" + jvmMetricFormat + ":" + jvmMetricType;
    }

    public String getPlatformName() {
      return platformName;
    }

    /**
     * @return the packageRoot
     */
    public File getPackageRoot() {
      return packageRoot;
    }

    public File getDartSdkPath() {
      return dartSdkPath;
    }

    /**
     * Returns whether warnings from SDK files should be suppressed.
     */
    public boolean suppressSdkWarnings() {
      return !showSdkWarnings;
    }
    
    /**
     * Returns whether inferred types should be used for type checks.
     */
    public boolean typeChecksForInferredTypes() {
      return false;
    }
    
    /**
     * Returns whether "no such member" should be reported for classes which implement
     * "noSuchMethod" method.
     */
    public boolean reportNoMemberWhenHasInterceptor() {
      return true;
    }
    
    /**
     * Returns the list of files passed to the compiler.
     */
    public List<String> getSourceFiles() {
      return sourceFiles;
    }

    /**
     * Returns the path to receive compiler intermediate output.
     */
    public File getWorkDirectory() {
      return workDirectory;
    }

    public boolean ignoreUnrecognizedFlags() {
      return ignoreUnrecognizedFlags;
    }

    /**
     * Returns whether the compiler should attempt to incrementally recompile.
     */
    public boolean buildIncrementally() {
      return incremental;
    }

    public boolean shouldBatch() {
      return batch;
    }

    public boolean resolveDespiteParseErrors() {
      return resolveDespiteParseErrors;
    }
    
    /**
     * Returns <code>true</code> if the compiler should print it's help message.
     */
    public boolean showHelp() {
      return showHelp;
    }

    public boolean showJvmMetrics() {
      return showJvmMetrics;
    }

    public boolean showMetrics() {
      return showMetrics;
    }

    public boolean showVersion() {
      return showVersion;
    }

    /**
     * if <code>true</code>, run the AST back through the DartSourceVisitor to create source
     * from the parsed AST and print to stdout.
     */
    public boolean showSourceFromAst() {
      return showSourceFromAst;
    }
    
    /**
     * Returns whether type errors are fatal.
     */
    public boolean typeErrorsAreFatal() {
      return typeErrorsAreFatal;
    }

    /**
     * Returns whether warnings (excluding type warnings) are fatal.
     */
    public boolean warningsAreFatal() {
      return warningsAreFatal;
    }

    public boolean developerModeChecks() {
      return developerModeChecks;
    }

    /**
     * @return the format to use for printing errors
     */
    public ErrorFormat printErrorFormat() {
      String lowerError = errorFormat.toLowerCase();
      if ("machine".equals(lowerError)) {
        return ErrorFormat.MACHINE;
      }
      return ErrorFormat.NORMAL;
    }
  }

  /**
   * Parses command line options, handling the feature to ignore unrecognized
   * flags.
   *
   * If one of the options is 'ignore-unrecognized-flags', then any exceptions
   * for 'not a valid option' are suppressed.
   *
   * @param args Arguments passed from main()
   * @param parsedOptions [out parameter] parsed options
   * @throws CmdLineException Thrown if there is a problem parsing the options.
   */
  public static CmdLineParser parse(String[] args, CompilerOptions parsedOptions)
      throws CmdLineException {
    // convert new "--name=value" into old "--name value" style
    {
      List<String> argList = Lists.newArrayList();
      for (String arg : args) {
        String[] parts = StringUtils.split(arg, '=');
        Collections.addAll(argList, parts);
      }
      args = argList.toArray(new String[argList.size()]);
    }

    boolean ignoreUnrecognized = false;
    for (String arg : args) {
      if (arg.equals("--ignore-unrecognized-flags")) {
        ignoreUnrecognized = true;
        break;
      }
    }

    if (!ignoreUnrecognized) {
      CmdLineParser cmdLineParser = new CmdLineParser(parsedOptions);
      cmdLineParser.parseArgument(args);
      return cmdLineParser;
    }
    CmdLineParser cmdLineParser = new CmdLineParser(parsedOptions);
    for (int i = 0, len = args.length; i < len; i++) {
      try {
        cmdLineParser.parseArgument(args);
      } catch (CmdLineException e) {
        String msg = e.getMessage();

        if (e.getMessage().endsWith(" is not a valid option")) {
          String option = msg.substring(1);
          int closeQuote = option.indexOf('\"');
          option = option.substring(0, closeQuote);
          List<String> newArgs = Lists.newArrayList();
          for (String arg : args) {
            if (arg.equals(option)) {
              System.out.println("(Ignoring unrecognized flag: " + arg + ")");
              continue;
            }
            newArgs.add(arg);
          }
          args = newArgs.toArray(new String[newArgs.size()]);
          cmdLineParser = new CmdLineParser(parsedOptions);
          continue;
        }
      }
      break;
    }
    return cmdLineParser;
  }
}
