// 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/source/line_info.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'abstract_single_unit.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(PassThroughMergingTest);
  });
}

/// Tests to make sure the algorithm used by [EditPlaner.passThrough] is
/// correct.
@reflectiveTest
class PassThroughMergingTest extends AbstractSingleUnitTest {
  Future<void> test_creates_pass_through_plans_stepwise() async {
    await resolveTestUnit('var x = [[[1]]];');
    var plan = _EditPlannerForTesting(testCode!).passThrough(
        findNode.listLiteral('[[['),
        innerPlans: [_MockPlan(findNode.integerLiteral('1'))]);
    expect(plan.toString(),
        'plan([[[1]]], [plan([[1]], [plan([1], [plan(1)])])])');
  }

  Future<void> test_merge_plans_at_lower_level() async {
    await resolveTestUnit('var x = [[1, 2]];');
    var plan = _EditPlannerForTesting(testCode!)
        .passThrough(findNode.listLiteral('[['), innerPlans: [
      _MockPlan(findNode.integerLiteral('1')),
      _MockPlan(findNode.integerLiteral('2'))
    ]);
    expect(
        plan.toString(), 'plan([[1, 2]], [plan([1, 2], [plan(1), plan(2)])])');
  }

  Future<void> test_merge_plans_at_top_level() async {
    await resolveTestUnit('var x = [[1], [2]];');
    var plan = _EditPlannerForTesting(testCode!)
        .passThrough(findNode.listLiteral('[['), innerPlans: [
      _MockPlan(findNode.integerLiteral('1')),
      _MockPlan(findNode.integerLiteral('2'))
    ]);
    expect(plan.toString(),
        'plan([[1], [2]], [plan([1], [plan(1)]), plan([2], [plan(2)])])');
  }

  Future<void> test_merge_plans_at_varying_levels() async {
    await resolveTestUnit('var x = [1, [2, 3], 4];');
    var plan = _EditPlannerForTesting(testCode!)
        .passThrough(findNode.listLiteral('[1'), innerPlans: [
      _MockPlan(findNode.integerLiteral('1')),
      _MockPlan(findNode.integerLiteral('2')),
      _MockPlan(findNode.integerLiteral('3')),
      _MockPlan(findNode.integerLiteral('4'))
    ]);
    expect(
        plan.toString(),
        'plan([1, [2, 3], 4], [plan(1), plan([2, 3], [plan(2), plan(3)]), '
        'plan(4)])');
  }
}

class _EditPlannerForTesting extends EditPlanner {
  _EditPlannerForTesting(String content)
      : super(LineInfo.fromContent(content), content);

  @override
  PassThroughBuilder createPassThroughBuilder(AstNode? node) =>
      _MockPassThroughBuilder(node);
}

class _MockPassThroughBuilder implements PassThroughBuilder {
  final List<EditPlan> _innerPlans = [];

  @override
  final AstNode? node;

  _MockPassThroughBuilder(this.node);

  @override
  void add(EditPlan innerPlan) {
    _innerPlans.add(innerPlan);
  }

  @override
  NodeProducingEditPlan finish(EditPlanner planner) {
    return _MockPlan(node, _innerPlans);
  }
}

class _MockPlan implements NodeProducingEditPlan {
  final AstNode? _node;

  final List<EditPlan> _innerPlans;

  _MockPlan(this._node, [List<EditPlan> innerPlans = const []])
      : _innerPlans = innerPlans;

  @override
  AstNode? get parentNode => _node!.parent;

  @override
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  @override
  String toString() =>
      _innerPlans.isEmpty ? 'plan($_node)' : 'plan($_node, $_innerPlans)';
}
