// 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.

// @dart = 2.9

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;

Directory outDir;

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) != 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];
    bool initializeExpect = initializationData[1];
    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.kind == ReferenceNameKind.Member &&
          otherName.kind == ReferenceNameKind.Member &&
          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');
  }
}
