// 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.
  if (field.getterCanonicalName.parent.name != "@fields") {
    throw "Expected @fields parent, but had "
        "${field.getterCanonicalName.parent.name}";
  }
  if (field.setterCanonicalName.parent.name != "@=fields") {
    throw "Expected @=fields 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 (setter.canonicalName.parent.name != "@setters") {
    throw "Expected @setters parent, but had "
        "${setter.canonicalName.parent.name}";
  }

  // 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 != "@fields") {
    throw "Expected @fields parent, but had "
        "${fieldReplacement.getterCanonicalName.parent.name}";
  }
  if (fieldReplacement.setterCanonicalName.parent.name != "@=fields") {
    throw "Expected @=fields 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;
}
