// Copyright (c) 2020, 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:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/cider/fixes.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'cider_service.dart';

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(CiderFixesComputerTest);
  });
}

@reflectiveTest
class CiderFixesComputerTest extends CiderServiceTest {
  late _CorrectionContext _correctionContext;
  late List<CiderErrorFixes> _errorsFixes;

  void assertHasFix(FixKind kind, String expected) {
    var fix = _getFix(kind);

    var fileEdits = fix.change.edits;
    expect(fileEdits, hasLength(1));

    var resultContent = SourceEdit.applySequence(
      _correctionContext.content,
      fileEdits.single.edits,
    );
    expect(resultContent, expected);
  }

  Future<void> test_cachedResolvedFiles() async {
    await _compute(r'''
var a = 0^ var b = 1
''');

    // Only the first fix is applied.
    assertHasFix(DartFixKind.INSERT_SEMICOLON, r'''
var a = 0; var b = 1
''');

    // The file was resolved only once, even though we have 2 errors.
    expect(fileResolver.testView!.resolvedFiles, [convertPath(testPath)]);
  }

  Future<void> test_createMethod() async {
    await _compute(r'''
class A {
}

void f(A a) {
  a.foo(0);^
}
''');

    assertHasFix(DartFixKind.CREATE_METHOD, r'''
class A {
  void foo(int i) {}
}

void f(A a) {
  a.foo(0);
}
''');
  }

  Future<void> test_insertSemicolon() async {
    await _compute(r'''
var v = 0^
''');

    assertHasFix(DartFixKind.INSERT_SEMICOLON, r'''
var v = 0;
''');
  }

  Future<void> _compute(String content) async {
    _updateFile(content);

    _errorsFixes = await CiderFixesComputer(
      logger,
      fileResolver,
    ).compute(
      convertPath(testPath),
      _correctionContext.line,
    );
  }

  Fix _getFix(FixKind kind) {
    for (var errorFixes in _errorsFixes) {
      for (var fix in errorFixes.fixes) {
        if (fix.kind == kind) {
          return fix;
        }
      }
    }
    fail('No fix $kind');
  }

  void _updateFile(String content) {
    var offset = content.indexOf('^');
    expect(offset, isPositive, reason: 'Expected to find ^');
    expect(content.indexOf('^', offset + 1), -1, reason: 'Expected only one ^');

    var lineInfo = LineInfo.fromContent(content);
    var location = lineInfo.getLocation(offset);

    content = content.substring(0, offset) + content.substring(offset + 1);
    newFile(testPath, content: content);

    _correctionContext = _CorrectionContext(
      content,
      offset,
      location.lineNumber,
      location.columnNumber,
    );
  }
}

class _CorrectionContext {
  final String content;
  final int offset;
  final int line;
  final int character;

  _CorrectionContext(this.content, this.offset, this.line, this.character);
}
