// Copyright (c) 2018, 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:io' show Directory, File;

import 'package:expect/expect.dart' show Expect;

import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;

import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;

import 'package:kernel/ast.dart';
import 'package:kernel/src/equivalence.dart';
import 'package:kernel/target/targets.dart';

import 'incremental_suite.dart'
    show checkIsEqual, getOptions, initializedCompile, normalCompile;

late Directory outDir;

Future<void> main() async {
  outDir =
      Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
  try {
    await testDart2jsCompile();
    print("----");
  } finally {
    outDir.deleteSync(recursive: true);
  }
}

Future<void> testDart2jsCompile() async {
  final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
  final Uri invalidateUri =
      Uri.parse("package:_fe_analyzer_shared/src/util/filenames.dart");
  Uri normalDill = outDir.uri.resolve("dart2js.full.dill");
  Uri fullDillFromInitialized =
      outDir.uri.resolve("dart2js.full_from_initialized.dill");
  Uri nonexisting = outDir.uri.resolve("dart2js.nonexisting.dill");

  // Compile dart2js without initializing from dill.
  // Note: Use none-target to avoid mismatches in "interface target" caused by
  // type inference occurring before or after mixin transformation.
  Stopwatch stopwatch = new Stopwatch()..start();
  await normalCompile(dart2jsUrl, normalDill,
      options: getOptions(target: new NoneTarget(new TargetFlags())));
  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
  {
    // Check that we don't include the source from files from the sdk.
    final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
    Uri platformUri = sdkRoot.resolve("vm_platform_strong.dill");
    Component cSdk = new Component();
    new BinaryBuilder(new File.fromUri(platformUri).readAsBytesSync(),
            disableLazyReading: false)
        .readComponent(cSdk);

    Component c = new Component();
    new BinaryBuilder(new File.fromUri(normalDill).readAsBytesSync(),
            disableLazyReading: false)
        .readComponent(c);
    for (Uri uri in c.uriToSource.keys) {
      if (cSdk.uriToSource.containsKey(uri)) {
        if (c.uriToSource[uri]!.source.length != 0) {
          throw "Compile contained sources for the sdk $uri";
        }
        if ((c.uriToSource[uri]!.lineStarts?.length ?? 0) != 0) {
          throw "Compile contained line starts for the sdk $uri";
        }
      }
    }
  }

  // Compile dart2js, initializing from the just-compiled dill,
  // a nonexisting file.
  for (List<Object> initializationData in [
    [normalDill, true],
    [nonexisting, false],
  ]) {
    Uri initializeWith = initializationData[0] as Uri;
    bool initializeExpect = initializationData[1] as bool;
    stopwatch.reset();
    bool initializeResult = await initializedCompile(
        dart2jsUrl, fullDillFromInitialized, initializeWith, [invalidateUri],
        options: getOptions(target: new NoneTarget(new TargetFlags())));
    Expect.equals(initializeExpect, initializeResult);
    print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
        "took ${stopwatch.elapsedMilliseconds} ms");

    // Compare the two files.
    List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
    List<int> initializedDillData =
        new File.fromUri(fullDillFromInitialized).readAsBytesSync();

    Component component1 = new Component();
    new BinaryBuilder(normalDillData).readComponent(component1);

    Component component2 = new Component();
    new BinaryBuilder(initializedDillData).readComponent(component2);
    EquivalenceResult result =
        checkEquivalence(component1, component2, strategy: const Strategy());
    Expect.isTrue(result.isEquivalent, result.toString());

    // TODO(johnniwinther): Reenable this check when the discrepancies have been
    // fixed.
    //checkIsEqual(normalDillData, initializedDillData);

    // Also try without invalidating anything.
    stopwatch.reset();
    initializeResult = await initializedCompile(
        dart2jsUrl, fullDillFromInitialized, initializeWith, [],
        options: getOptions(target: new NoneTarget(new TargetFlags())));
    Expect.equals(initializeExpect, initializeResult);
    print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
        "took ${stopwatch.elapsedMilliseconds} ms");

    // Compare the two files.
    initializedDillData =
        new File.fromUri(fullDillFromInitialized).readAsBytesSync();
    checkIsEqual(normalDillData, initializedDillData);
  }
}

class Strategy extends EquivalenceStrategy {
  const Strategy();

  @override
  bool checkClass_procedures(
      EquivalenceVisitor visitor, Class node, Class other) {
    // Check procedures as a set instead of a list to allow for reordering.
    return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
        visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
  }

  bool _isMixinOrCloneReference(EquivalenceVisitor visitor, Reference? a,
      Reference? b, String propertyName) {
    if (a != null && b != null) {
      ReferenceName thisName = ReferenceName.fromReference(a)!;
      ReferenceName otherName = ReferenceName.fromReference(b)!;
      if (thisName.isMember &&
          otherName.isMember &&
          thisName.memberName == otherName.memberName) {
        String? thisClassName = thisName.declarationName;
        String? otherClassName = otherName.declarationName;
        if (thisClassName != null &&
            otherClassName != null &&
            thisClassName.contains('&${otherClassName}')) {
          visitor.assumeReferences(a, b);
        }
      }
    }
    return visitor.checkReferences(a, b, propertyName);
  }

  @override
  bool checkProcedure_stubTargetReference(
      EquivalenceVisitor visitor, Procedure node, Procedure other) {
    return _isMixinOrCloneReference(visitor, node.stubTargetReference,
        other.stubTargetReference, 'stubTargetReference');
  }

  @override
  bool checkInstanceGet_interfaceTargetReference(
      EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
    return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
        other.interfaceTargetReference, 'interfaceTargetReference');
  }
}
