// Copyright (c) 2017, 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:convert';
import 'dart:io';

import 'package:kernel/ast.dart';
import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/text/ast_to_text.dart';
import 'package:test/test.dart';
import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;

/// Test metadata: to each node we attach a metadata that contains
/// * node formatted as string
/// * reference to its enclosing member
/// * type representing the first type parameter of its enclosing function
class Metadata {
  final String string;
  final Reference? _memberRef;
  final DartType type;

  Member? get member => _memberRef?.asMember;

  Metadata.forNode(TreeNode n)
      : this(
            n.leakingDebugToString(),
            // Refers to the member, not about the function => use getter.
            getMemberReferenceGetter(getMemberForMetadata(n)),
            getTypeForMetadata(n));

  Metadata(this.string, this._memberRef, this.type);
}

Member? getMemberForMetadata(TreeNode node) {
  final parent = node.parent;
  if (parent == null) return null;
  if (parent is Member) return parent;
  return getMemberForMetadata(parent);
}

DartType getTypeForMetadata(TreeNode node) {
  final parent = node.parent;
  if (parent == null) return const VoidType();
  if (parent is FunctionNode) {
    if (parent.typeParameters.isEmpty) {
      return const VoidType();
    }
    return new TypeParameterType(parent.typeParameters[0], Nullability.legacy);
  }
  return getTypeForMetadata(parent);
}

class TestMetadataRepository extends MetadataRepository<Metadata> {
  static const kTag = 'kernel.metadata.test';

  @override
  final String tag = kTag;

  @override
  final Map<TreeNode, Metadata> mapping = <TreeNode, Metadata>{};

  @override
  void writeToBinary(Metadata metadata, Node node, BinarySink sink) {
    expect(metadata, equals(mapping[node]));
    sink.writeByteList(utf8.encode(metadata.string));
    sink.writeStringReference(metadata.string);
    sink.writeNullAllowedCanonicalNameReference(
        metadata.member?.reference.canonicalName);
    sink.writeDartType(metadata.type);
  }

  @override
  Metadata readFromBinary(Node node, BinarySource source) {
    final string1 = utf8.decode(source.readByteList());
    final string2 = source.readStringReference();
    final memberRef = source.readNullableCanonicalNameReference()?.reference;
    final type = source.readDartType();
    expect(string1, equals(string2));
    return new Metadata(string2, memberRef, type);
  }
}

class BytesBuilderSink implements Sink<List<int>> {
  final builder = new BytesBuilder(copy: false);

  @override
  void add(List<int> bytes) {
    builder.add(bytes);
  }

  @override
  void close() {}
}

typedef NodePredicate = bool Function(TreeNode node);

/// Visitor calling [handle] function on every node which can have metadata
/// associated with it and also satisfies the given [predicate].
class Visitor extends RecursiveVisitor {
  final NodePredicate predicate;
  final void Function(TreeNode) handle;

  Visitor(this.predicate, this.handle);

  @override
  void defaultTreeNode(TreeNode node) {
    super.defaultTreeNode(node);
    if (MetadataRepository.isSupported(node) && predicate(node)) {
      handle(node);
    }
  }
}

/// Visit the given component assigning [Metadata] object created with
/// [Metadata.forNode] to each supported node in the component which matches
/// [shouldAnnotate] predicate.
void annotate(Component p, NodePredicate shouldAnnotate) {
  globalDebuggingNames = new NameSystem();
  final repository = p.metadata[TestMetadataRepository.kTag]!;
  p.accept(new Visitor(shouldAnnotate, (node) {
    repository.mapping[node] = new Metadata.forNode(node);
  }));
}

/// Visit the given component and checks that each supported node in the
/// component matching [shouldAnnotate] predicate has correct metadata.
void validate(Component p, NodePredicate shouldAnnotate) {
  globalDebuggingNames = new NameSystem();
  final repository = p.metadata[TestMetadataRepository.kTag]!;
  p.accept(new Visitor(shouldAnnotate, (node) {
    final m = repository.mapping[node];
    final expected = new Metadata.forNode(node);

    expect(m, isNotNull);
    expect(m.string, equals(expected.string));
    expect(m.member, equals(expected.member));
    expect(m.type, equals(expected.type));
  }));
}

Component fromBinary(List<int> bytes) {
  var component = new Component();
  component.addMetadataRepository(new TestMetadataRepository());
  new BinaryBuilderWithMetadata(bytes).readComponent(component);
  return component;
}

List<int> toBinary(Component p) {
  final sink = new BytesBuilderSink();
  new BinaryPrinter(sink).writeComponentFile(p);
  return sink.builder.takeBytes();
}

void main() async {
  bool anyNode(TreeNode node) => true;
  bool onlyMethods(TreeNode node) =>
      node is Procedure &&
      node.kind == ProcedureKind.Method &&
      node.enclosingClass != null;

  final Uri platform = computePlatformBinariesLocation(forceBuildDir: true)
      .resolve("vm_platform_strong.dill");
  final List<int> platformBinary =
      await new File(platform.toFilePath()).readAsBytes();

  Future<void> testRoundTrip(List<int> Function(List<int>) binaryTransformer,
      NodePredicate shouldAnnotate) async {
    final component = fromBinary(platformBinary);
    annotate(component, shouldAnnotate);
    validate(component, shouldAnnotate);
    expect(component.metadata[TestMetadataRepository.kTag]!.mapping.length,
        greaterThan(0));

    final annotatedComponentBinary = binaryTransformer(toBinary(component));
    final annotatedComponentFromBinary = fromBinary(annotatedComponentBinary);
    validate(annotatedComponentFromBinary, shouldAnnotate);
    expect(
        annotatedComponentFromBinary
            .metadata[TestMetadataRepository.kTag]!.mapping.length,
        greaterThan(0));
  }

  test('annotate-serialize-deserialize-validate', () async {
    await testRoundTrip((binary) => binary, anyNode);
  });

  test('annotate-serialize-deserialize-validate-only-methods', () async {
    await testRoundTrip((binary) => binary, onlyMethods);
  });

  test('annotate-serialize-deserialize-twice-then-validate', () async {
    // This test validates that serializing a component that was just
    // deserialized (without visiting anything) works.
    await testRoundTrip((binary) => toBinary(fromBinary(binary)), anyNode);
  });

  test('annotate-serialize-deserialize-twice-then-validate-only-methods',
      () async {
    // This test validates that serializing a component that was just
    // deserialized (without visiting anything) works.
    await testRoundTrip((binary) => toBinary(fromBinary(binary)), onlyMethods);
  });
}
