// Copyright (c) 2020, 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.

// @dart = 2.9

import 'dart:convert' show jsonDecode;

import 'dart:io' show File;

import 'crashing_test_case_minimizer_impl.dart';

// TODO(jensj): Option to automatically find and search for _all_ crashes that
// it uncovers --- i.e. it currently has an option to ask if we want to search
// for the other crash instead --- add an option so it does that automatically
// for everything it sees. One can possibly just make a copy of the state of
// the file system and save that for later...

// TODO(jensj): Add asserts or similar where - after each rewrite - we run the
// parser on it and verifies that no syntax errors have been introduced.

Future<void> main(List<String> arguments) async {
  String filename;
  Uri loadJson;
  for (String arg in arguments) {
    if (arg.startsWith("--json=")) {
      String json = arg.substring("--json=".length);
      loadJson = Uri.base.resolve(json);
      break;
    }
  }
  TestMinimizerSettings settings = new TestMinimizerSettings();

  if (loadJson != null) {
    File f = new File.fromUri(loadJson);
    settings.initializeFromJson((jsonDecode(f.readAsStringSync())));
  } else {
    for (String arg in arguments) {
      if (arg.startsWith("--")) {
        if (arg == "--experimental-invalidation") {
          settings.experimentalInvalidation = true;
        } else if (arg == "--serialize") {
          settings.serialize = true;
        } else if (arg.startsWith("--platform=")) {
          String platform = arg.substring("--platform=".length);
          settings.platformUri = Uri.base.resolve(platform);
        } else if (arg == "--no-platform") {
          settings.noPlatform = true;
        } else if (arg.startsWith("--invalidate=")) {
          for (String s in arg.substring("--invalidate=".length).split(",")) {
            settings.invalidate.add(Uri.base.resolve(s));
          }
        } else if (arg.startsWith("--widgetTransformation")) {
          settings.widgetTransformation = true;
        } else if (arg.startsWith("--target=VM")) {
          settings.targetString = "VM";
        } else if (arg.startsWith("--target=flutter")) {
          settings.targetString = "flutter";
        } else if (arg.startsWith("--target=ddc")) {
          settings.targetString = "ddc";
        } else if (arg.startsWith("--target=dart2js")) {
          settings.targetString = "dart2js";
        } else if (arg == "--noTryToDeleteEmptyFilesUpFront") {
          settings.noTryToDeleteEmptyFilesUpFront = true;
        } else if (arg.startsWith("--wantErrorOnReload=")) {
          String wantErrorOnReload =
              arg.substring("--wantErrorOnReload=".length);
          settings.lookForErrorErrorOnReload = wantErrorOnReload;
        } else if (arg == "--oldBlockDelete") {
          settings.oldBlockDelete = true;
        } else if (arg == "--lineDelete") {
          settings.lineDelete = true;
        } else if (arg == "--byteDelete") {
          settings.byteDelete = true;
        } else if (arg == "--ask-redirect-target") {
          settings.askAboutRedirectCrashTarget = true;
        } else if (arg == "--auto-uncover-all-crashes") {
          settings.autoUncoverAllCrashes = true;
        } else if (arg.startsWith("--stack-matches=")) {
          String stackMatches = arg.substring("--stack-matches=".length);
          settings.stackTraceMatches = int.parse(stackMatches);
        } else {
          throw "Unknown option $arg";
        }
      } else if (filename != null) {
        throw "Already got '$filename', '$arg' is also a filename; "
            "can only get one";
      } else {
        filename = arg;
      }
    }
    if (settings.noPlatform) {
      int i = 0;
      while (settings.platformUri == null ||
          new File.fromUri(settings.platformUri).existsSync()) {
        settings.platformUri = Uri.base.resolve("nonexisting_$i");
        i++;
      }
    } else {
      if (settings.platformUri == null) {
        throw "No platform given. Use --platform=/path/to/platform.dill";
      }
      if (!new File.fromUri(settings.platformUri).existsSync()) {
        throw "The platform file '${settings.platformUri}' doesn't exist";
      }
    }
    if (filename == null) {
      throw "Need file to operate on";
    }
    File file = new File(filename);
    if (!file.existsSync()) throw "File $filename doesn't exist.";
    settings.mainUri = file.absolute.uri;
  }

  TestMinimizer testMinimizer = new TestMinimizer(settings);
  await testMinimizer.tryToMinimize();
}
