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

// @dart = 2.9

import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/src/tool/find_referenced_libraries.dart';
import 'binary/utils.dart';

main() {
  Component component1 = createComponent(42);
  Component component2 = createComponent(43);

  expectReachable(
      findAllReferencedLibraries(component1.libraries), component1.libraries);
  if (duplicateLibrariesReachable(component1.libraries)) {
    throw "Didn't expect duplicates libraries!";
  }
  expectReachable(
      findAllReferencedLibraries(component2.libraries), component2.libraries);
  if (duplicateLibrariesReachable(component2.libraries)) {
    throw "Didn't expect duplicates libraries!";
  }

  ByteSink sink = new ByteSink();
  new BinaryPrinter(sink).writeComponentFile(component1);
  List<int> writtenBytes1 = sink.builder.takeBytes();
  sink = new ByteSink();
  new BinaryPrinter(sink).writeComponentFile(component2);
  List<int> writtenBytes2 = sink.builder.takeBytes();

  // Loading a single one works as one would expect: It's linked to itself.
  Component component1Prime = new Component();
  new BinaryBuilder(writtenBytes1).readSingleFileComponent(component1Prime);
  Procedure target1 = getMainTarget(component1Prime);
  Procedure procedureLib1 = getLibProcedure(component1Prime);
  if (target1 != procedureLib1) throw "Unexpected target.";
  expectReachable(findAllReferencedLibraries(component1Prime.libraries),
      component1Prime.libraries);
  if (duplicateLibrariesReachable(component1Prime.libraries)) {
    throw "Didn't expect duplicates libraries!";
  }

  // Loading another one saying it should overwrite works as one would expect
  // for this component: It gives a component that is linked to itself that is
  // different from the one loaded "on top of".
  Component component2Prime = new Component(nameRoot: component1Prime.root);
  new BinaryBuilder(writtenBytes2, alwaysCreateNewNamedNodes: true)
      .readSingleFileComponent(component2Prime);
  Procedure target2 = getMainTarget(component2Prime);
  Procedure procedureLib2 = getLibProcedure(component2Prime);
  if (procedureLib2 == procedureLib1) throw "Unexpected procedure.";
  if (target2 != procedureLib2) throw "Unexpected target.";
  expectReachable(findAllReferencedLibraries(component2Prime.libraries),
      component2Prime.libraries);
  if (duplicateLibrariesReachable(component2Prime.libraries)) {
    throw "Didn't expect duplicates libraries!";
  }

  // The old one that was loaded on top of was re-linked so it also points to
  // procedureLib2.
  target1 = getMainTarget(component1Prime);
  if (target1 != procedureLib2) throw "Unexpected target.";

  // Relink back and forth a number of times: It keeps working as expected.
  for (int i = 0; i < 6; i++) {
    // Before the relink the lib from component2Prime is also reachable!
    expectReachable(
        findAllReferencedLibraries(component1Prime.libraries),
        []
          ..addAll(component1Prime.libraries)
          ..add(procedureLib2.enclosingLibrary));
    if (!duplicateLibrariesReachable(component1Prime.libraries)) {
      throw "Expected duplicates libraries!";
    }

    // Relinking component1Prime works as one would expected: Both components
    // main now points to procedureLib1.
    component1Prime.relink();
    // After the relink only the libs from component1Prime are reachable!
    expectReachable(findAllReferencedLibraries(component1Prime.libraries),
        component1Prime.libraries);
    if (duplicateLibrariesReachable(component1Prime.libraries)) {
      throw "Didn't expect duplicates libraries!";
    }
    target1 = getMainTarget(component1Prime);
    if (target1 != procedureLib1) throw "Unexpected target.";
    target2 = getMainTarget(component2Prime);
    if (target2 != procedureLib1) throw "Unexpected target.";

    // Before the relink the lib from component1Prime is also reachable!
    expectReachable(
        findAllReferencedLibraries(component2Prime.libraries),
        []
          ..addAll(component2Prime.libraries)
          ..add(procedureLib1.enclosingLibrary));
    if (!duplicateLibrariesReachable(component2Prime.libraries)) {
      throw "Expected duplicates libraries!";
    }
    // Relinking component2Prime works as one would expected: Both components
    // main now points to procedureLib2.
    component2Prime.relink();
    // After the relink only the libs from component1Prime are reachable!
    expectReachable(findAllReferencedLibraries(component2Prime.libraries),
        component2Prime.libraries);
    if (duplicateLibrariesReachable(component2Prime.libraries)) {
      throw "Didn't expect duplicates libraries!";
    }
    target1 = getMainTarget(component1Prime);
    if (target1 != procedureLib2) throw "Unexpected target.";
    target2 = getMainTarget(component2Prime);
    if (target2 != procedureLib2) throw "Unexpected target.";
  }
}

void expectReachable(
    Set<Library> findAllReferencedLibraries, List<Library> libraries) {
  Set<Library> onlyInReferenced = findAllReferencedLibraries.toSet()
    ..removeAll(libraries);
  Set<Library> onlyInLibraries = libraries.toSet()
    ..removeAll(findAllReferencedLibraries);
  if (onlyInReferenced.isNotEmpty || onlyInLibraries.isNotEmpty) {
    throw "Expected to be the same, but ${onlyInReferenced} was only in "
        "reachable and ${onlyInLibraries} was only in libraries";
  }
}

Procedure getLibProcedure(Component component1Prime) {
  if (component1Prime.libraries[1].importUri !=
      Uri.parse('org-dartlang:///lib.dart')) {
    throw "Expected lib second, got ${component1Prime.libraries[1].importUri}";
  }
  Procedure procedureLib = component1Prime.libraries[1].procedures[0];
  return procedureLib;
}

Procedure getMainTarget(Component component1Prime) {
  if (component1Prime.libraries[0].importUri !=
      Uri.parse('org-dartlang:///main.dart')) {
    throw "Expected main first, got ${component1Prime.libraries[0].importUri}";
  }
  Block block = component1Prime.libraries[0].procedures[0].function.body;
  ReturnStatement returnStatement = block.statements[0];
  StaticInvocation staticInvocation = returnStatement.expression;
  Procedure target = staticInvocation.target;
  return target;
}

Component createComponent(int literal) {
  final Uri libUri = Uri.parse('org-dartlang:///lib.dart');
  final Library lib = new Library(libUri, fileUri: libUri);
  final Block libProcedureBody =
      new Block([new ReturnStatement(new IntLiteral(literal))]);
  final Procedure libProcedure = new Procedure(
      new Name("method"),
      ProcedureKind.Method,
      new FunctionNode(libProcedureBody, returnType: new DynamicType()),
      fileUri: libUri);
  lib.addProcedure(libProcedure);

  final Uri mainUri = Uri.parse('org-dartlang:///main.dart');
  final Library main = new Library(mainUri, fileUri: mainUri);
  final Block mainProcedureBody = new Block([
    new ReturnStatement(
        new StaticInvocation(libProcedure, new Arguments.empty()))
  ]);
  final Procedure mainProcedure = new Procedure(
      new Name("method"),
      ProcedureKind.Method,
      new FunctionNode(mainProcedureBody, returnType: new DynamicType()),
      fileUri: mainUri);
  main.addProcedure(mainProcedure);
  return new Component(libraries: [main, lib])
    ..setMainMethodAndMode(null, false, NonNullableByDefaultCompiledMode.Weak);
}
