// 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 {
    _setSelection();
    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 {
    _setSelection();
    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();
  }

  /// 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;
  }

  void _setSelection() {
    _offset = testCode.indexOf('/*caret*/');
    if (_offset >= 0) {
      _offset += '/*caret*/'.length;
      _length = 0;
    } else {
      _offset = testCode.indexOf('// start\n');
      if (_offset >= 0) {
        _offset += '// start\n'.length;
        _length = testCode.indexOf('// end') - _offset;
      } else {
        _offset = 0;
        _length = 0;
      }
    }
  }
}
