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

import "dart:developer";
import 'dart:io' show Platform;

import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/fasta/kernel/utils.dart';

import 'package:kernel/kernel.dart'
    show Component, Library, LibraryPart, Reference;

import 'incremental_load_from_dill_suite.dart' as helper;

import "incremental_utils.dart" as util;

main(List<String> args) async {
  bool fast = false;
  bool useExperimentalInvalidation = false;
  bool addDebugBreaks = false;
  int limit = -1;
  for (String arg in args) {
    if (arg == "--fast") {
      fast = true;
    } else if (arg == "--experimental") {
      useExperimentalInvalidation = true;
    } else if (arg == "--addDebugBreaks") {
      addDebugBreaks = true;
    } else if (arg.startsWith("--limit=")) {
      limit = int.parse(arg.substring("--limit=".length));
    } else {
      throw "Unsupported argument: $arg";
    }
  }

  Dart2jsTester dart2jsTester = new Dart2jsTester(
      useExperimentalInvalidation, fast, addDebugBreaks, limit);
  await dart2jsTester.test();
}

class Dart2jsTester {
  final bool useExperimentalInvalidation;
  final bool fast;
  final bool addDebugBreaks;
  final int limit;

  Stopwatch stopwatch = new Stopwatch();
  List<int> firstCompileData;
  Map<Uri, List<int>> libToData;
  List<Uri> uris;

  List<Uri> diffs = new List<Uri>();
  Set<Uri> componentUris = new Set<Uri>();

  Dart2jsTester(this.useExperimentalInvalidation, this.fast,
      this.addDebugBreaks, this.limit);

  void test() async {
    helper.TestIncrementalCompiler compiler = await setup();
    if (addDebugBreaks) {
      debugger();
    }

    diffs = new List<Uri>();
    componentUris = new Set<Uri>();

    Stopwatch localStopwatch = new Stopwatch()..start();
    int recompiles = 0;
    for (int i = 0; i < uris.length; i++) {
      if (limit >= 0 && limit < i) break;
      recompiles++;
      Uri uri = uris[i];
      await step(uri, i, compiler, localStopwatch);
    }

    print("A total of ${diffs.length} diffs:");
    for (Uri uri in diffs) {
      print(" - $uri");
    }

    print("Done after ${recompiles} recompiles in "
        "${stopwatch.elapsedMilliseconds} ms");
  }

  Future step(Uri uri, int i, helper.TestIncrementalCompiler compiler,
      Stopwatch localStopwatch) async {
    print("Invalidating $uri ($i)");
    compiler.invalidate(uri);
    localStopwatch.reset();
    Component c2 = await compiler.computeDelta(fullComponent: true);
    print("Recompiled in ${localStopwatch.elapsedMilliseconds} ms");
    print("invalidatedImportUrisForTesting: "
        "${compiler.invalidatedImportUrisForTesting}");
    print("rebuildBodiesCount: ${compiler.rebuildBodiesCount}");
    localStopwatch.reset();
    Set<Uri> thisUris = new Set<Uri>.from(c2.libraries.map((l) => l.importUri));
    if (componentUris.isNotEmpty) {
      Set<Uri> diffUris = {};
      diffUris.addAll(thisUris.difference(componentUris));
      diffUris.addAll(componentUris.difference(thisUris));
      if (diffUris.isNotEmpty) {
        print("Diffs for this compile: $diffUris");
      }
    }
    componentUris.clear();
    componentUris.addAll(thisUris);

    if (fast) {
      print("Got ${c2.libraries.length} libraries");
      c2.libraries.sort((l1, l2) {
        return "${l1.fileUri}".compareTo("${l2.fileUri}");
      });

      c2.problemsAsJson?.sort();

      c2.computeCanonicalNames();

      int foundCount = 0;
      for (Library library in c2.libraries) {
        Set<Uri> uris = new Set<Uri>();
        uris.add(library.importUri);
        for (LibraryPart part in library.parts) {
          Uri uri = library.importUri.resolve(part.partUri);
          uris.add(uri);
        }
        if (!uris.contains(uri)) continue;
        foundCount++;
        library.additionalExports.sort((Reference r1, Reference r2) {
          return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
        });
        library.problemsAsJson?.sort();

        List<int> libSerialized =
            serializeComponent(c2, filter: (l) => l == library);
        if (!isEqual(libToData[library.importUri], libSerialized)) {
          print("=====");
          print("=====");
          print("=====");
          print("Notice diff on $uri ($i)!");
          libToData[library.importUri] = libSerialized;
          diffs.add(uri);
          print("=====");
          print("=====");
          print("=====");
        }
      }
      if (foundCount != 1) {
        throw "Expected to find $uri, but it $foundCount times.";
      }
      print("Serialized library in ${localStopwatch.elapsedMilliseconds} ms");
    } else {
      List<int> thisCompileData = util.postProcess(c2);
      print("Serialized in ${localStopwatch.elapsedMilliseconds} ms");
      if (!isEqual(firstCompileData, thisCompileData)) {
        print("=====");
        print("=====");
        print("=====");
        print("Notice diff on $uri ($i)!");
        firstCompileData = thisCompileData;
        diffs.add(uri);
        print("=====");
        print("=====");
        print("=====");
      }
    }
    if (addDebugBreaks) {
      debugger();
    }
    print("-----");
  }

  Future<helper.TestIncrementalCompiler> setup() async {
    stopwatch.reset();
    stopwatch.start();
    Uri input = Platform.script.resolve("../../compiler/bin/dart2js.dart");
    CompilerOptions options = helper.getOptions();
    helper.TestIncrementalCompiler compiler =
        new helper.TestIncrementalCompiler(options, input);
    compiler.useExperimentalInvalidation = useExperimentalInvalidation;
    Component c = await compiler.computeDelta();
    print("Compiled dart2js to Component with ${c.libraries.length} libraries "
        "in ${stopwatch.elapsedMilliseconds} ms.");
    stopwatch.reset();
    if (fast) {
      libToData = {};
      c.libraries.sort((l1, l2) {
        return "${l1.fileUri}".compareTo("${l2.fileUri}");
      });

      c.problemsAsJson?.sort();

      c.computeCanonicalNames();

      for (Library library in c.libraries) {
        library.additionalExports.sort((Reference r1, Reference r2) {
          return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
        });
        library.problemsAsJson?.sort();

        List<int> libSerialized =
            serializeComponent(c, filter: (l) => l == library);
        libToData[library.importUri] = libSerialized;
      }
    } else {
      firstCompileData = util.postProcess(c);
    }
    print("Serialized in ${stopwatch.elapsedMilliseconds} ms");
    stopwatch.reset();

    uris = c.uriToSource.values
        .map((s) => s != null ? s.importUri : null)
        .where((u) => u != null && u.scheme != "dart")
        .toSet()
        .toList();

    c = null;

    return compiler;
  }

  bool isEqual(List<int> a, List<int> b) {
    int length = a.length;
    if (b.length != length) {
      return false;
    }
    for (int i = 0; i < length; ++i) {
      if (a[i] != b[i]) {
        return false;
      }
    }
    return true;
  }
}
