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

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:nnbd_migration/instrumentation.dart';
import 'package:nnbd_migration/src/conditional_discard.dart';
import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
import 'package:nnbd_migration/src/decorated_type.dart';
import 'package:nnbd_migration/src/edge_builder.dart';
import 'package:nnbd_migration/src/expression_checks.dart';
import 'package:nnbd_migration/src/node_builder.dart';
import 'package:nnbd_migration/src/nullability_node.dart';
import 'package:nnbd_migration/src/nullability_node_target.dart';
import 'package:nnbd_migration/src/variables.dart';
import 'package:test/test.dart';

import 'abstract_single_unit.dart';

/// A [NodeMatcher] that matches any node, and records what node it matched to.
class AnyNodeMatcher extends _RecordingNodeMatcher {
  @override
  bool matches(NullabilityNode? node) {
    return true;
  }
}

/// Mixin allowing unit tests to create decorated types easily.
mixin DecoratedTypeTester implements DecoratedTypeTesterBase {
  int nodeId = 0;

  NullabilityNode get always => graph.always;

  DecoratedType get bottom => DecoratedType(typeProvider.bottomType, never);

  DecoratedType get dynamic_ => DecoratedType(typeProvider.dynamicType, always);

  NullabilityNode get never => graph.never;

  DecoratedType get null_ => DecoratedType(typeProvider.nullType, always);

  DecoratedType get void_ => DecoratedType(typeProvider.voidType, always);

  DecoratedType function(DecoratedType returnType,
      {List<DecoratedType> required = const [],
      List<DecoratedType> positional = const [],
      Map<String, DecoratedType> named = const {},
      List<TypeParameterElement> typeFormals = const [],
      NullabilityNode? node}) {
    int i = 0;
    var parameters = required
        .map((t) => ParameterElementImpl.synthetic(
            'p${i++}', t.type!, ParameterKind.REQUIRED))
        .toList();
    parameters.addAll(positional.map((t) => ParameterElementImpl.synthetic(
        'p${i++}', t.type!, ParameterKind.POSITIONAL)));
    parameters.addAll(named.entries.map((e) => ParameterElementImpl.synthetic(
        e.key, e.value.type!, ParameterKind.NAMED)));
    return DecoratedType(
        FunctionTypeImpl(
          typeFormals: typeFormals,
          parameters: parameters,
          returnType: returnType.type!,
          nullabilitySuffix: NullabilitySuffix.star,
        ),
        node ?? newNode(),
        returnType: returnType,
        positionalParameters: required.toList()..addAll(positional),
        namedParameters: named);
  }

  DecoratedType future(DecoratedType parameter, {NullabilityNode? node}) {
    return DecoratedType(
        typeProvider.futureType(parameter.type!), node ?? newNode(),
        typeArguments: [parameter]);
  }

  DecoratedType futureOr(DecoratedType parameter, {NullabilityNode? node}) {
    return DecoratedType(
        typeProvider.futureOrType(parameter.type!), node ?? newNode(),
        typeArguments: [parameter]);
  }

  DecoratedType int_({NullabilityNode? node}) =>
      DecoratedType(typeProvider.intType, node ?? newNode());

  DecoratedType iterable(DecoratedType elementType, {NullabilityNode? node}) =>
      DecoratedType(
          typeProvider.iterableType(elementType.type!), node ?? newNode(),
          typeArguments: [elementType]);

  DecoratedType list(DecoratedType elementType, {NullabilityNode? node}) =>
      DecoratedType(typeProvider.listType(elementType.type!), node ?? newNode(),
          typeArguments: [elementType]);

  NullabilityNode newNode() => NullabilityNode.forTypeAnnotation(
      NullabilityNodeTarget.text('node ${nodeId++}'));

  DecoratedType num_({NullabilityNode? node}) =>
      DecoratedType(typeProvider.numType, node ?? newNode());

  DecoratedType object({NullabilityNode? node}) =>
      DecoratedType(typeProvider.objectType, node ?? newNode());

  TypeParameterElement typeParameter(String name, DecoratedType bound) {
    var element = TypeParameterElementImpl.synthetic(name);
    element.bound = bound.type;
    decoratedTypeParameterBounds.put(element, bound);
    return element;
  }

  DecoratedType typeParameterType(TypeParameterElement typeParameter,
      {NullabilityNode? node}) {
    return DecoratedType(
      typeParameter.instantiate(
        nullabilitySuffix: NullabilitySuffix.star,
      ),
      node ?? newNode(),
    );
  }
}

/// Base functionality that must be implemented by classes mixing in
/// [DecoratedTypeTester].
abstract class DecoratedTypeTesterBase {
  DecoratedTypeParameterBounds get decoratedTypeParameterBounds;

  NullabilityGraph get graph;

  TypeProvider get typeProvider;
}

class EdgeBuilderTestBase extends MigrationVisitorTestBase {
  DecoratedClassHierarchy? decoratedClassHierarchy;

  /// Analyzes the given source code, producing constraint variables and
  /// constraints for it.
  @override
  Future<CompilationUnit> analyze(String code) async {
    var unit = await super.analyze(code);
    decoratedClassHierarchy = DecoratedClassHierarchy(variables, graph);
    unit.accept(EdgeBuilder(
        typeProvider,
        typeSystem,
        variables,
        graph,
        testSource,
        null,
        decoratedClassHierarchy,
        unit.declaredElement!.library));
    return unit;
  }
}

/// Mixin allowing unit tests to check for the presence of graph edges.
mixin EdgeTester {
  /// Gets the set of all nodes pointed to by always, plus always itself.
  Set<NullabilityNode> get alwaysPlus {
    var result = <NullabilityNode>{graph.always};
    for (var edge in getEdges(graph.always, anyNode)) {
      if (edge.guards.isEmpty) {
        result.add(edge.destinationNode);
      }
    }
    return result;
  }

  /// Returns a [NodeMatcher] that matches any node whatsoever.
  AnyNodeMatcher get anyNode => AnyNodeMatcher();

  NullabilityGraphForTesting get graph;

  /// Gets the transitive closure of all nodes with hard edges pointing to
  /// never, plus never itself.
  Set<NullabilityNode?> get neverClosure {
    var result = <NullabilityNode?>{};
    var pending = <NullabilityNode?>[graph.never];
    while (pending.isNotEmpty) {
      var node = pending.removeLast();
      if (result.add(node)) {
        for (var edge in getEdges(anyNode, node)) {
          pending.add(edge.sourceNode);
        }
      }
    }
    return result;
  }

  /// Gets the set of nodes with hard edges pointing to never.
  Set<NullabilityNode?> get pointsToNever {
    return {for (var edge in getEdges(anyNode, graph.never)) edge.sourceNode};
  }

  /// Asserts that a dummy edge exists from [source] to always.
  NullabilityEdge assertDummyEdge(Object? source) =>
      assertEdge(source, graph.always, hard: false, checkable: false);

  /// Asserts that an edge exists with a node matching [source] and a node
  /// matching [destination], and with the given [hard]ness and [guards].
  ///
  /// [source] and [destination] are converted to [NodeMatcher] objects if they
  /// aren't already.  In practice this means that the caller can pass in either
  /// a [NodeMatcher] or a [NullabilityNode].
  NullabilityEdge assertEdge(Object? source, Object? destination,
      {required bool hard,
      bool checkable = true,
      bool isSetupAssignment = false,
      Object guards = isEmpty,
      Object? codeReference}) {
    var edges = getEdges(source, destination);
    if (edges.isEmpty) {
      fail('Expected edge $source -> $destination, found none');
    } else if (edges.length != 1) {
      fail('Found multiple edges $source -> $destination');
    } else {
      var edge = edges[0];
      expect(edge.isHard, hard);
      expect(edge.isCheckable, checkable);
      expect(edge.isSetupAssignment, isSetupAssignment);
      expect(edge.guards, guards);
      if (codeReference != null) {
        expect(edge.codeReference, codeReference);
      }
      return edge;
    }
  }

  /// Asserts that no edge exists with a node matching [source] and a node
  /// matching [destination].
  ///
  /// [source] and [destination] are converted to [NodeMatcher] objects if they
  /// aren't already.  In practice this means that the caller can pass in either
  /// a [NodeMatcher] or a [NullabilityNode].
  void assertNoEdge(Object? source, Object? destination) {
    var edges = getEdges(source, destination);
    if (edges.isNotEmpty) {
      fail('Expected no edge $source -> $destination, found $edges');
    }
  }

  /// Asserts that a union-type edge exists between nodes [x] and [y].
  ///
  /// [x] and [y] are converted to [NodeMatcher] objects if they aren't already.
  /// In practice this means that the caller can pass in either a [NodeMatcher]
  /// or a [NullabilityNode].
  void assertUnion(Object? x, Object? y) {
    var edges = getEdges(x, y);
    for (var edge in edges) {
      if (edge.isUnion) {
        expect(edge.upstreamNodes, hasLength(1));
        return;
      }
    }
    fail('Expected union between $x and $y, not found');
  }

  /// Gets a list of all edges whose source matches [source] and whose
  /// destination matches [destination].
  ///
  /// [source] and [destination] are converted to [NodeMatcher] objects if they
  /// aren't already.  In practice this means that the caller can pass in either
  /// a [NodeMatcher] or a [NullabilityNode].
  List<NullabilityEdge> getEdges(Object? source, Object? destination) {
    var sourceMatcher = NodeMatcher(source);
    var destinationMatcher = NodeMatcher(destination);
    var result = <NullabilityEdge>[];
    for (var edge in graph.getAllEdges()) {
      if (sourceMatcher.matches(edge.sourceNode) &&
          destinationMatcher.matches(edge.destinationNode)) {
        sourceMatcher.matched(edge.sourceNode);
        destinationMatcher.matched(edge.destinationNode);
        result.add(edge);
      }
    }
    return result;
  }

  /// Returns a [NodeMatcher] that matches any node in the given set.
  NodeSetMatcher inSet(Set<NullabilityNode?> nodes) => NodeSetMatcher(nodes);

  /// Creates a [NodeMatcher] matching a substitution node whose inner and outer
  /// nodes match [inner] and [outer].
  ///
  /// [inner] and [outer] are converted to [NodeMatcher] objects if they aren't
  /// already.  In practice this means that the caller can pass in either a
  /// [NodeMatcher] or a [NullabilityNode].
  NodeMatcher substitutionNode(Object? inner, Object? outer) =>
      _SubstitutionNodeMatcher(NodeMatcher(inner), NodeMatcher(outer));
}

/// Mock representation of constraint variables.
class InstrumentedVariables extends Variables {
  final _conditionalDiscard = <AstNode, ConditionalDiscard>{};

  final _decoratedExpressionTypes = <Expression, DecoratedType?>{};

  final _expressionChecks = <Expression, ExpressionChecksOrigin>{};

  InstrumentedVariables(super.graph, super.typeProvider);

  /// Gets the [ExpressionChecks] associated with the given [expression].
  ExpressionChecksOrigin? checkExpression(Expression expression) =>
      _expressionChecks[_normalizeExpression(expression)];

  /// Gets the [conditionalDiscard] associated with the given [expression].
  ConditionalDiscard? conditionalDiscard(AstNode node) =>
      _conditionalDiscard[node];

  /// Gets the [DecoratedType] associated with the given [expression].
  DecoratedType? decoratedExpressionType(Expression expression) =>
      _decoratedExpressionTypes[_normalizeExpression(expression)];

  @override
  void recordConditionalDiscard(
      Source? source, AstNode node, ConditionalDiscard conditionalDiscard) {
    _conditionalDiscard[node] = conditionalDiscard;
    super.recordConditionalDiscard(source, node, conditionalDiscard);
  }

  void recordDecoratedExpressionType(Expression node, DecoratedType? type) {
    super.recordDecoratedExpressionType(node, type);
    _decoratedExpressionTypes[_normalizeExpression(node)] = type;
  }

  @override
  void recordExpressionChecks(
      Source? source, Expression expression, ExpressionChecksOrigin origin) {
    super.recordExpressionChecks(source, expression, origin);
    _expressionChecks[_normalizeExpression(expression)] = origin;
  }

  /// Unwraps any parentheses surrounding [expression].
  Expression _normalizeExpression(Expression expression) {
    while (expression is ParenthesizedExpression) {
      expression = expression.expression;
    }
    return expression;
  }
}

class MigrationVisitorTestBase extends AbstractSingleUnitTest with EdgeTester {
  late InstrumentedVariables variables;

  final NullabilityGraphForTesting graph;

  final decoratedTypeParameterBounds = DecoratedTypeParameterBounds();

  MigrationVisitorTestBase() : this._(NullabilityGraphForTesting());

  MigrationVisitorTestBase._(this.graph);

  NullabilityNode get always => graph.always;

  NullabilityNode get never => graph.never;

  TypeProvider get typeProvider => testAnalysisResult.typeProvider;

  TypeSystemImpl get typeSystem =>
      testAnalysisResult.typeSystem as TypeSystemImpl;

  Future<CompilationUnit> analyze(String code) async {
    await resolveTestUnit(code);
    variables = InstrumentedVariables(graph, typeProvider);
    testUnit!
        .accept(NodeBuilder(variables, testSource, null, graph, typeProvider));
    return testUnit!;
  }

  /// Gets the [DecoratedType] associated with the constructor declaration whose
  /// name matches [search].
  DecoratedType decoratedConstructorDeclaration(String search) => variables
      .decoratedElementType(findNode.constructor(search).declaredElement2!);

  Map<InterfaceElement, DecoratedType?> decoratedDirectSupertypes(String name) {
    return variables.decoratedDirectSupertypes(findElement.classOrMixin(name));
  }

  /// Gets the [DecoratedType] associated with the generic function type
  /// annotation whose text is [text].
  DecoratedType decoratedGenericFunctionTypeAnnotation(String text) {
    return variables.decoratedTypeAnnotation(
        testSource, findNode.genericFunctionType(text));
  }

  /// Gets the [DecoratedType] associated with the method declaration whose
  /// name matches [search].
  DecoratedType decoratedMethodType(String search) =>
      variables.decoratedElementType(
          findNode.methodDeclaration(search).declaredElement2!);

  /// Gets the [DecoratedType] associated with the type annotation whose text
  /// is [text].
  DecoratedType decoratedTypeAnnotation(String text) {
    return variables.decoratedTypeAnnotation(
        testSource, findNode.typeAnnotation(text));
  }

  /// Gets the [ConditionalDiscard] information associated with the collection
  /// element whose text is [text].
  ConditionalDiscard? elementDiscard(String text) {
    return variables.conditionalDiscard(findNode.collectionElement(text));
  }

  /// Returns a [Matcher] that matches a [CodeReference] pointing to the given
  /// file [offset], with the given [function] name.
  TypeMatcher<CodeReference> matchCodeRef(
      {required int offset, required String function}) {
    var location = testUnit!.lineInfo.getLocation(offset);
    return TypeMatcher<CodeReference>()
        .having((cr) => cr.line, 'line', location.lineNumber)
        .having((cr) => cr.column, 'column', location.columnNumber)
        .having((cr) => cr.function, 'function', function);
  }

  void setUp() {
    DecoratedTypeParameterBounds.current = decoratedTypeParameterBounds;
    super.setUp();
  }

  /// Gets the [ConditionalDiscard] information associated with the statement
  /// whose text is [text].
  ConditionalDiscard? statementDiscard(String text) {
    return variables.conditionalDiscard(findNode.statement(text));
  }

  void tearDown() {
    DecoratedTypeParameterBounds.current = null;
    super.tearDown();
  }
}

/// Abstract base class representing a thing that can be matched against
/// nullability nodes.
abstract class NodeMatcher {
  factory NodeMatcher(Object? expectation) {
    if (expectation is NodeMatcher) return expectation;
    if (expectation is NullabilityNode) return _ExactNodeMatcher(expectation);
    fail(
        'Unclear how to match node expectation of type ${expectation.runtimeType}');
  }

  void matched(NullabilityNode? node);

  bool matches(NullabilityNode? node);
}

/// A [NodeMatcher] that matches any node contained in the given set.
class NodeSetMatcher extends _RecordingNodeMatcher {
  final Set<NullabilityNode?> _targetSet;

  NodeSetMatcher(this._targetSet);

  @override
  bool matches(NullabilityNode? node) => _targetSet.contains(node);
}

/// A [NodeMatcher] that matches exactly one node.
class _ExactNodeMatcher implements NodeMatcher {
  final NullabilityNode _expectation;

  _ExactNodeMatcher(this._expectation);

  @override
  void matched(NullabilityNode? node) {}

  @override
  bool matches(NullabilityNode? node) => node == _expectation;
}

/// Base class for [NodeMatcher]s that remember which nodes were matched.
abstract class _RecordingNodeMatcher implements NodeMatcher {
  final List<NullabilityNode?> _matchingNodes = [];

  NullabilityNode? get matchingNode => _matchingNodes.single;

  @override
  void matched(NullabilityNode? node) {
    _matchingNodes.add(node);
  }
}

/// A [NodeMatcher] that matches a substitution node with the given inner and
/// outer nodes.
class _SubstitutionNodeMatcher implements NodeMatcher {
  final NodeMatcher inner;
  final NodeMatcher outer;

  _SubstitutionNodeMatcher(this.inner, this.outer);

  @override
  void matched(NullabilityNode? node) {
    if (node is NullabilityNodeForSubstitution) {
      inner.matched(node.innerNode);
      outer.matched(node.outerNode);
    } else {
      throw StateError(
          'matched should only be called on nodes for which matches returned '
          'true');
    }
  }

  @override
  bool matches(NullabilityNode? node) {
    return node is NullabilityNodeForSubstitution &&
        inner.matches(node.innerNode) &&
        outer.matches(node.outerNode);
  }
}
