// Copyright (c) 2017, the R8 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.android.tools.r8.bisect;

import com.android.tools.r8.errors.CompilationError;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;

public class BisectOptions {
  private static final String HELP_FLAG = "help";
  public static final String BUILD_GOOD_FLAG = "good";
  public static final String BUILD_BAD_FLAG = "bad";
  public static final String RESULT_GOOD_FLAG = "result-good";
  public static final String RESULT_BAD_FLAG = "result-bad";
  public static final String STATE_FLAG = "state";
  public static final String OUTPUT_FLAG = "output";
  public static final String COMMAND_FLAG = "command";

  public final Path goodBuild;
  public final Path badBuild;
  public final Path stateFile;
  public final Path command;
  public final Path output;
  public final Result result;

  public enum Result { UNKNOWN, GOOD, BAD }

  private static class ParserSpec {
    OptionSpec<String> goodBuild;
    OptionSpec<String> badBuild;
    OptionSpec<String> command;
    OptionSpec<String> stateFile;
    OptionSpec<String> output;
    OptionSpec<Void> resultGood;
    OptionSpec<Void> resultBad;
    OptionSpec<Void> help;

    void init(OptionParser parser) {
      help = parser.accepts(HELP_FLAG).forHelp();
      resultGood = parser.accepts(RESULT_GOOD_FLAG, "Bisect again assuming previous run was good.");
      resultBad = parser.accepts(RESULT_BAD_FLAG, "Bisect again assuming previous run was bad.");
      goodBuild = parser.accepts(BUILD_GOOD_FLAG, "Known good APK.")
          .withRequiredArg()
          .describedAs("apk");
      badBuild = parser.accepts(BUILD_BAD_FLAG, "Known bad APK.")
          .withRequiredArg()
          .describedAs("apk");
      stateFile = parser.accepts(STATE_FLAG, "Bisection state.")
          .requiredIf(resultGood, resultBad)
          .withRequiredArg()
          .describedAs("file");
      output = parser.accepts(OUTPUT_FLAG, "Output directory.")
          .withRequiredArg()
          .describedAs("dir");
      command = parser.accepts(COMMAND_FLAG, "Command to run after each bisection.")
          .requiredUnless(stateFile)
          .withRequiredArg()
          .describedAs("file");
    }

    OptionSet parse(String[] args) {
      OptionParser parser = new OptionParser();
      init(parser);
      return parser.parse(args);
    }

    static void printHelp(OutputStream out) throws IOException {
      OptionParser parser = new OptionParser();
      new ParserSpec().init(parser);
      parser.printHelpOn(out);
    }
  }

  private BisectOptions(
      Path goodBuild, Path badBuild, Path stateFile, Path command, Path output, Result result) {
    this.goodBuild = goodBuild;
    this.badBuild = badBuild;
    this.stateFile = stateFile;
    this.command = command;
    this.output = output;
    this.result = result;
  }

  public static BisectOptions parse(String[] args) throws IOException {
    ParserSpec parser = new ParserSpec();
    OptionSet options = parser.parse(args);
    if (options.has(parser.help)) {
      printHelp(System.out);
      return null;
    }
    Path goodBuild = exists(require(options, parser.goodBuild, BUILD_GOOD_FLAG), BUILD_GOOD_FLAG);
    Path badBuild = exists(require(options, parser.badBuild, BUILD_BAD_FLAG), BUILD_BAD_FLAG);
    Path stateFile = null;
    if (options.valueOf(parser.stateFile) != null) {
      stateFile = exists(options.valueOf(parser.stateFile), STATE_FLAG);
    }
    Path command = null;
    if (options.valueOf(parser.command) != null) {
      command = exists(options.valueOf(parser.command), COMMAND_FLAG);
    }
    Path output = null;
    if (options.valueOf(parser.output) != null) {
      output = directoryExists(options.valueOf(parser.output), OUTPUT_FLAG);
    }
    Result result = Result.UNKNOWN;
    if (options.has(parser.resultGood)) {
      result = Result.GOOD;
    }
    if (options.has(parser.resultBad)) {
      if (result == Result.GOOD) {
        throw new CompilationError("Cannot specify --" + RESULT_GOOD_FLAG
            + " and --" + RESULT_BAD_FLAG + " simultaneously");
      }
      result = Result.BAD;
    }
    return new BisectOptions(goodBuild, badBuild, stateFile, command, output, result);
  }

  private static <T> T require(OptionSet options, OptionSpec<T> option, String flag) {
    T value = options.valueOf(option);
    if (value != null) {
      return value;
    }
    throw new CompilationError("Missing required option: --" + flag);
  }

  private static Path exists(String path, String flag) {
    Path file = Paths.get(path);
    if (Files.exists(file)) {
      return file;
    }
    throw new CompilationError("File --" + flag + ": " + file + " does not exist");
  }

  private static Path directoryExists(String path, String flag) {
    Path file = Paths.get(path);
    if (Files.exists(file) && Files.isDirectory(file)) {
      return file;
    }
    throw new CompilationError("File --" + flag + ": " + file + " is not a valid directory");
  }

  public static void printHelp(OutputStream out) throws IOException {
    ParserSpec.printHelp(out);
  }
}
