// 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 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'binary/utils.dart';

main() {
  final Library lib1 = new Library(Uri.parse('org-dartlang:///lib.dart'));
  final Field field = new Field.mutable(new Name("f"));
  lib1.addField(field);
  final Block libProcedureBody = new Block([
    new ExpressionStatement(new StaticSet(field, new IntLiteral(42))),
    new ReturnStatement(new StaticGet(field)),
  ]);
  final Procedure libProcedure = new Procedure(
      new Name("method"),
      ProcedureKind.Method,
      new FunctionNode(libProcedureBody, returnType: new DynamicType()));
  lib1.addProcedure(libProcedure);

  final Library lib2 = new Library(Uri.parse('org-dartlang:///lib2.dart'));
  final Block lib2ProcedureBody = new Block([
    new ExpressionStatement(new StaticSet(field, new IntLiteral(43))),
    new ReturnStatement(new StaticGet(field)),
  ]);
  final Procedure lib2Procedure = new Procedure(
      new Name("method"),
      ProcedureKind.Method,
      new FunctionNode(lib2ProcedureBody, returnType: new DynamicType()));
  lib2.addProcedure(lib2Procedure);

  verifyTargets(libProcedure, lib2Procedure, field, field);
  List<int> writtenBytesFieldOriginal = serialize(lib1, lib2);
  // Canonical names are now set: Verify that the field is marked as such,
  // canonical-name-wise.
  String getterCanonicalName = '${field.getterCanonicalName}';
  if (field.getterCanonicalName.parent.name != "@getters") {
    throw "Expected @getters parent, but had "
        "${field.getterCanonicalName.parent.name}";
  }
  String setterCanonicalName = '${field.setterCanonicalName}';
  if (field.setterCanonicalName.parent.name != "@setters") {
    throw "Expected @setters parent, but had "
        "${field.setterCanonicalName.parent.name}";
  }

  // Replace the field with a setter/getter pair.
  lib1.fields.remove(field);
  FunctionNode getterFunction = new FunctionNode(new Block([]));
  Procedure getter = new Procedure(
      new Name("f"), ProcedureKind.Getter, getterFunction,
      reference: field.getterReference);
  // Important: Unbind any old canonical name
  // (nulling out the canonical name is not enough because it leaves the old
  // canonical name (which always stays alive) with a pointer to the reference,
  // meaning that if one tried to rebind it (e.g. if going back to a field from
  // a setter/getter), the reference wouldn't (because of the way `bindTo` is
  // implemented) actually have it's canonical name set, and serialization
  // wouldn't work.)
  field.getterReference?.canonicalName?.unbind();
  lib1.addProcedure(getter);

  FunctionNode setterFunction = new FunctionNode(new Block([]),
      positionalParameters: [new VariableDeclaration("foo")]);
  Procedure setter = new Procedure(
      new Name("f"), ProcedureKind.Setter, setterFunction,
      reference: field.setterReference);
  // Important: Unbind any old canonical name
  // (nulling out the canonical name is not enough, see above).
  field.setterReference?.canonicalName?.unbind();
  lib1.addProcedure(setter);

  verifyTargets(libProcedure, lib2Procedure, getter, setter);
  List<int> writtenBytesGetterSetter = serialize(lib1, lib2);
  // Canonical names are now set: Verify that the getter/setter is marked as
  // such, canonical-name-wise.
  if (getter.canonicalName.parent.name != "@getters") {
    throw "Expected @getters parent, but had "
        "${getter.canonicalName.parent.name}";
  }
  if ('${getter.canonicalName}' != getterCanonicalName) {
    throw "Unexpected getter canonical name. "
        "Expected $getterCanonicalName, actual ${getter.canonicalName}.";
  }
  if (setter.canonicalName.parent.name != "@setters") {
    throw "Expected @setters parent, but had "
        "${setter.canonicalName.parent.name}";
  }
  if ('${setter.canonicalName}' != setterCanonicalName) {
    throw "Unexpected setter canonical name. "
        "Expected $setterCanonicalName, actual ${setter.canonicalName}.";
  }

  // Replace getter/setter with field.
  lib1.procedures.remove(getter);
  lib1.procedures.remove(setter);
  final Field fieldReplacement = new Field.mutable(new Name("f"),
      getterReference: getter.reference, setterReference: setter.reference);
  // Important: Unbind any old canonical name
  // (nulling out the canonical name is not enough, see above).
  fieldReplacement.getterReference?.canonicalName?.unbind();
  fieldReplacement.setterReference?.canonicalName?.unbind();
  lib1.addField(fieldReplacement);

  verifyTargets(
      libProcedure, lib2Procedure, fieldReplacement, fieldReplacement);
  List<int> writtenBytesFieldNew = serialize(lib1, lib2);
  // Canonical names are now set: Verify that the field is marked as such,
  // canonical-name-wise.
  if (fieldReplacement.getterCanonicalName.parent.name != "@getters") {
    throw "Expected @getters parent, but had "
        "${fieldReplacement.getterCanonicalName.parent.name}";
  }
  if (fieldReplacement.setterCanonicalName.parent.name != "@setters") {
    throw "Expected @setters parent, but had "
        "${fieldReplacement.setterCanonicalName.parent.name}";
  }

  // Load the written stuff and ensure it is as expected.
  // First one has a field.
  Component componentLoaded = new Component();
  new BinaryBuilder(writtenBytesFieldOriginal)
      .readSingleFileComponent(componentLoaded);
  verifyTargets(
      componentLoaded.libraries[0].procedures.single,
      componentLoaded.libraries[1].procedures.single,
      componentLoaded.libraries[0].fields.single,
      componentLoaded.libraries[0].fields.single);

  // Second one has a getter/setter pair.
  componentLoaded = new Component();
  new BinaryBuilder(writtenBytesGetterSetter)
      .readSingleFileComponent(componentLoaded);
  assert(componentLoaded.libraries[0].procedures[2].isSetter);
  verifyTargets(
      componentLoaded.libraries[0].procedures[0],
      componentLoaded.libraries[1].procedures[0],
      componentLoaded.libraries[0].procedures[1],
      componentLoaded.libraries[0].procedures[2]);

  // Third one has a field again.
  componentLoaded = new Component();
  new BinaryBuilder(writtenBytesFieldNew)
      .readSingleFileComponent(componentLoaded);
  verifyTargets(
      componentLoaded.libraries[0].procedures.single,
      componentLoaded.libraries[1].procedures.single,
      componentLoaded.libraries[0].fields.single,
      componentLoaded.libraries[0].fields.single);
}

void verifyTargets(Procedure libProcedure, Procedure lib2Procedure,
    Member getterTarget, Member setterTarget) {
  if (getGetTarget(libProcedure) != getterTarget) {
    throw "Unexpected get target for lib #1";
  }
  if (getSetTarget(libProcedure) != setterTarget) {
    throw "Unexpected set target for lib #1";
  }
  if (getGetTarget(lib2Procedure) != getterTarget) {
    throw "Unexpected get target for lib #2";
  }
  if (getSetTarget(lib2Procedure) != setterTarget) {
    throw "Unexpected set target for lib #2";
  }
}

List<int> serialize(Library lib1, Library lib2) {
  Component component = new Component(libraries: [lib1, lib2])
    ..setMainMethodAndMode(null, false, NonNullableByDefaultCompiledMode.Weak);
  ByteSink sink = new ByteSink();
  new BinaryPrinter(sink).writeComponentFile(component);
  return sink.builder.takeBytes();
}

Member getSetTarget(Procedure p) {
  Block block = p.function.body;
  ExpressionStatement getterStatement = block.statements[0];
  StaticSet staticSet = getterStatement.expression;
  return staticSet.target;
}

Member getGetTarget(Procedure p) {
  Block block = p.function.body;
  ReturnStatement setterStatement = block.statements[1];
  StaticGet staticGet = setterStatement.expression;
  return staticGet.target;
}
