// 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.File;
import java.io.IOException;
import java.io.OutputStream;
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 File goodBuild;
  public final File badBuild;
  public final File stateFile;
  public final File command;
  public final File 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(File goodBuild, File badBuild, File stateFile, File command, File 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;
    }
    File goodBuild = exists(require(options, parser.goodBuild, BUILD_GOOD_FLAG), BUILD_GOOD_FLAG);
    File badBuild = exists(require(options, parser.badBuild, BUILD_BAD_FLAG), BUILD_BAD_FLAG);
    File stateFile = null;
    if (options.valueOf(parser.stateFile) != null) {
      stateFile = exists(options.valueOf(parser.stateFile), STATE_FLAG);
    }
    File command = null;
    if (options.valueOf(parser.command) != null) {
      command = exists(options.valueOf(parser.command), COMMAND_FLAG);
    }
    File 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)
      throws IOException {
    T value = options.valueOf(option);
    if (value != null) {
      return value;
    }
    throw new CompilationError("Missing required option: --" + flag);
  }

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

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

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