// Copyright (c) 2018, 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:async';

import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    hide AnalysisError;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
import 'package:test/test.dart';

import '../../../../abstract_single_unit.dart';

/// A base class defining support for writing assist processor tests.
abstract class AssistProcessorTest extends AbstractSingleUnitTest {
  int _offset;
  int _length;

  SourceChange _change;
  String _resultCode;

  /// Return the kind of assist expected by this class.
  AssistKind get kind;

  /// The workspace in which fixes contributor operates.
  ChangeWorkspace get workspace {
    return DartChangeWorkspace([session]);
  }

  void assertExitPosition({String before, String after}) {
    Position exitPosition = _change.selection;
    expect(exitPosition, isNotNull);
    expect(exitPosition.file, testFile);
    if (before != null) {
      expect(exitPosition.offset, _resultCode.indexOf(before));
    } else if (after != null) {
      expect(exitPosition.offset, _resultCode.indexOf(after) + after.length);
    } else {
      fail("One of 'before' or 'after' expected.");
    }
  }

  /// Asserts that there is an assist of the given [kind] at [_offset] which
  /// produces the [expected] code when applied to [testCode]. The map of
  /// [additionallyChangedFiles] can be used to test assists that can modify
  /// more than the test file. The keys are expected to be the paths to the
  /// files that are modified (other than the test file) and the values are
  /// pairs of source code: the states of the code before and after the edits
  /// have been applied.
  Future<void> assertHasAssist(String expected,
      {Map<String, List<String>> additionallyChangedFiles}) async {
    Assist assist = await _assertHasAssist();
    _change = assist.change;
    expect(_change.id, kind.id);
    // apply to "file"
    List<SourceFileEdit> fileEdits = _change.edits;
    if (additionallyChangedFiles == null) {
      expect(fileEdits, hasLength(1));
      _resultCode = SourceEdit.applySequence(testCode, _change.edits[0].edits);
      expect(_resultCode, expected);
    } else {
      expect(fileEdits, hasLength(additionallyChangedFiles.length + 1));
      _resultCode = SourceEdit.applySequence(
          testCode, _change.getFileEdit(testFile).edits);
      expect(_resultCode, expected);
      for (String filePath in additionallyChangedFiles.keys) {
        List<String> pair = additionallyChangedFiles[filePath];
        String resultCode = SourceEdit.applySequence(
            pair[0], _change.getFileEdit(filePath).edits);
        expect(resultCode, pair[1]);
      }
    }
  }

  /// Asserts that there is an [Assist] of the given [kind] at the offset of the
  /// given [snippet] which produces the [expected] code when applied to [testCode].
  Future<void> assertHasAssistAt(String snippet, String expected,
      {int length = 0}) async {
    _offset = findOffset(snippet);
    _length = length;
    Assist assist = await _assertHasAssist();
    _change = assist.change;
    expect(_change.id, kind.id);
    // apply to "file"
    List<SourceFileEdit> fileEdits = _change.edits;
    expect(fileEdits, hasLength(1));
    _resultCode = SourceEdit.applySequence(testCode, _change.edits[0].edits);
    expect(_resultCode, expected);
  }

  void assertLinkedGroup(int groupIndex, List<String> expectedStrings,
      [List<LinkedEditSuggestion> expectedSuggestions]) {
    LinkedEditGroup group = _change.linkedEditGroups[groupIndex];
    List<Position> expectedPositions = _findResultPositions(expectedStrings);
    expect(group.positions, unorderedEquals(expectedPositions));
    if (expectedSuggestions != null) {
      expect(group.suggestions, unorderedEquals(expectedSuggestions));
    }
  }

  /// Asserts that there is no [Assist] of the given [kind] at [_offset].
  Future<void> assertNoAssist() async {
    List<Assist> assists = await _computeAssists();
    for (Assist assist in assists) {
      if (assist.kind == kind) {
        fail('Unexpected assist $kind in\n${assists.join('\n')}');
      }
    }
  }

  /// Asserts that there is no [Assist] of the given [kind] at the offset of the
  /// given [snippet].
  Future<void> assertNoAssistAt(String snippet, {int length = 0}) async {
    _offset = findOffset(snippet);
    _length = length;
    List<Assist> assists = await _computeAssists();
    for (Assist assist in assists) {
      if (assist.kind == kind) {
        fail('Unexpected assist $kind in\n${assists.join('\n')}');
      }
    }
  }

  List<LinkedEditSuggestion> expectedSuggestions(
      LinkedEditSuggestionKind kind, List<String> values) {
    return values.map((value) {
      return new LinkedEditSuggestion(value, kind);
    }).toList();
  }

  @override
  Future<void> resolveTestUnit(String code) async {
    var offset = code.indexOf('/*caret*/');
    if (offset >= 0) {
      var endOffset = offset + '/*caret*/'.length;
      code = code.substring(0, offset) + code.substring(endOffset);
      _offset = offset;
      _length = 0;
    } else {
      var startOffset = code.indexOf('// start\n');
      var endOffset = code.indexOf('// end\n');
      if (startOffset >= 0 && endOffset >= 0) {
        var startLength = '// start\n'.length;
        code = code.substring(0, startOffset) +
            code.substring(startOffset + startLength, endOffset) +
            code.substring(endOffset + '// end\n'.length);
        _offset = startOffset;
        _length = endOffset - startLength - _offset;
      } else {
        _offset = 0;
        _length = 0;
      }
    }
    return super.resolveTestUnit(code);
  }

  /// Computes assists and verifies that there is an assist of the given kind.
  Future<Assist> _assertHasAssist() async {
    List<Assist> assists = await _computeAssists();
    for (Assist assist in assists) {
      if (assist.kind == kind) {
        return assist;
      }
    }
    fail('Expected to find assist $kind in\n${assists.join('\n')}');
  }

  Future<List<Assist>> _computeAssists() async {
    var context = new DartAssistContextImpl(
      workspace,
      testAnalysisResult,
      _offset,
      _length,
    );
    var processor = new AssistProcessor(context);
    return await processor.compute();
  }

  List<Position> _findResultPositions(List<String> searchStrings) {
    List<Position> positions = <Position>[];
    for (String search in searchStrings) {
      int offset = _resultCode.indexOf(search);
      positions.add(new Position(testFile, offset));
    }
    return positions;
  }
}
