// Copyright (c) 2021, 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 'package:expect/expect.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/clone.dart';
import 'package:kernel/src/coverage.dart';
import 'package:kernel/src/equivalence.dart';
import 'package:kernel/src/node_creator.dart';

void main() {
  testBodyCloning();
  testBodyCloningInContext();
  testMemberCloning();
}

void testBodyCloning() {
  // TODO(johnniwinther): Add a test for cloning in context.
  NodeCreator creator =
      new NodeCreator(initializers: [], members: [], nodes: inBodyNodeKinds);
  List<TreeNode> nodes = creator.generateBodies();

  CoverageVisitor coverageVisitor = new CoverageVisitor();
  for (TreeNode node in nodes) {
    node.accept(coverageVisitor);
    CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
    TreeNode clone = cloner.clone(node);
    EquivalenceResult result = checkEquivalence(node, clone,
        strategy: const NoFileOffsetEquivalenceStrategy());
    if (!result.isEquivalent) {
      print(result);
    }
    Expect.isTrue(result.isEquivalent, "$node");
  }
  Expect.isEmpty(
      creator.createdKinds.toSet()..removeAll(coverageVisitor.visited),
      'Nodes not covered in testing.');
}

void testBodyCloningInContext() {
  NodeCreator creator =
      new NodeCreator(initializers: [], members: [], nodes: inBodyNodeKinds);
  List<Statement> nodes = creator.generateBodies();

  CoverageVisitor coverageVisitor = new CoverageVisitor();
  for (Statement node in nodes) {
    node.accept(coverageVisitor);
    CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
    // Set up context for [statement].
    new Procedure(Name('foo'), ProcedureKind.Method, FunctionNode(node),
        fileUri: dummyUri);
    TreeNode clone = cloner.cloneInContext(node);
    EquivalenceResult result = checkEquivalence(node, clone);
    if (!result.isEquivalent) {
      print(result);
    }
    Expect.isTrue(result.isEquivalent, "$node");
  }
  Expect.isEmpty(
      creator.createdKinds.toSet()..removeAll(coverageVisitor.visited),
      'Nodes not covered in testing.');
}

void testMemberCloning() {
  NodeCreator creator = new NodeCreator(nodes: inBodyNodeKinds);
  Component component = creator.generateComponent();

  CoverageVisitor coverageVisitor = new CoverageVisitor();

  void testMembers<M extends Member>(
      Iterable<M> members,
      M Function(CloneVisitorWithMembers, M) cloneFunction,
      String Function(M) toStringFunction) {
    for (M member in members) {
      member.accept(coverageVisitor);
      CloneVisitorWithMembers cloner = new CloneVisitorWithMembers();
      M clone = cloneFunction(cloner, member);
      EquivalenceResult result = checkEquivalence(member, clone,
          strategy: const MemberEquivalenceStrategy());
      if (!result.isEquivalent) {
        print(result);
      }
      Expect.isTrue(result.isEquivalent, toStringFunction(member));
    }
  }

  void testProcedures(Iterable<Procedure> procedures) {
    testMembers<Procedure>(
        procedures,
        (cloner, procedure) => cloner.cloneProcedure(procedure, null),
        (procedure) => "${procedure.runtimeType}(${procedure.name}):"
            "${procedure.function.body}");
  }

  void testFields(Iterable<Field> fields) {
    testMembers<Field>(
        fields,
        (cloner, field) => cloner.cloneField(field, null, null, null),
        (field) => "${field.runtimeType}(${field.name}):"
            "${field.initializer}");
  }

  void testConstructors(Iterable<Constructor> constructors) {
    testMembers<Constructor>(
        constructors,
        (cloner, constructor) => cloner.cloneConstructor(constructor, null),
        (constructor) => "${constructor.runtimeType}(${constructor.name}):"
            "${constructor.initializers}:"
            "${constructor.function.body}");
  }

  void testRedirectingFactories(
      Iterable<RedirectingFactory> redirectingFactory) {
    testMembers<RedirectingFactory>(
        redirectingFactory,
        (cloner, redirectingFactory) =>
            cloner.cloneRedirectingFactory(redirectingFactory, null),
        (redirectingFactory) =>
            "${redirectingFactory.runtimeType}(${redirectingFactory.name}):"
            "${redirectingFactory.function.body}");
  }

  for (Library library in component.libraries) {
    testProcedures(library.procedures);
    testFields(library.fields);
    for (Class cls in library.classes) {
      testProcedures(cls.procedures);
      testFields(cls.fields);
      testConstructors(cls.constructors);
      testRedirectingFactories(cls.redirectingFactories);
    }
  }
  Expect.isEmpty(
      creator.createdKinds.toSet()..removeAll(coverageVisitor.visited),
      'Nodes not covered in testing.');
}

class NoFileOffsetEquivalenceStrategy extends EquivalenceStrategy {
  const NoFileOffsetEquivalenceStrategy();

  @override
  bool checkTreeNode_fileOffset(
      EquivalenceVisitor visitor, TreeNode node, TreeNode other) {
    if (other.fileOffset == TreeNode.noOffset) return true;
    return super.checkTreeNode_fileOffset(visitor, node, other);
  }
}

class MemberEquivalenceStrategy extends EquivalenceStrategy {
  const MemberEquivalenceStrategy();

  void assumeClonedReferences(EquivalenceVisitor visitor, Member member1,
      Reference? reference1, Member member2, Reference? reference2) {
    if (reference1 != null && reference2 != null) {
      ReferenceName referenceName1 = ReferenceName.fromNamedNode(member1);
      ReferenceName referenceName2 = ReferenceName.fromNamedNode(member2);
      if (referenceName1.kind == referenceName2.kind &&
              referenceName1.memberName == referenceName2.memberName &&
              referenceName1.memberUri == referenceName2.memberUri &&
              referenceName2.declarationName == null ||
          referenceName2.libraryUri == null) {
        visitor.assumeReferences(reference1, reference2);
      }
    }
  }

  @override
  bool checkProcedure(
      EquivalenceVisitor visitor, Procedure? node, Object? other) {
    if (node is Procedure && other is Procedure) {
      assumeClonedReferences(
          visitor, node, node.reference, other, other.reference);
    }
    return super.checkProcedure(visitor, node, other);
  }

  @override
  bool checkConstructor(
      EquivalenceVisitor visitor, Constructor? node, Object? other) {
    if (node is Constructor && other is Constructor) {
      assumeClonedReferences(
          visitor, node, node.reference, other, other.reference);
    }
    return super.checkConstructor(visitor, node, other);
  }

  @override
  bool checkRedirectingFactory(
      EquivalenceVisitor visitor, RedirectingFactory? node, Object? other) {
    if (node is RedirectingFactory && other is RedirectingFactory) {
      assumeClonedReferences(
          visitor, node, node.reference, other, other.reference);
    }
    return super.checkRedirectingFactory(visitor, node, other);
  }

  @override
  bool checkField(EquivalenceVisitor visitor, Field? node, Object? other) {
    if (node is Field && other is Field) {
      assumeClonedReferences(
          visitor, node, node.fieldReference, other, other.fieldReference);
      assumeClonedReferences(
          visitor, node, node.getterReference, other, other.getterReference);
      assumeClonedReferences(
          visitor, node, node.setterReference, other, other.setterReference);
    }
    return super.checkField(visitor, node, other);
  }
}
