// Copyright (c) 2015, 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/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../analysis_server_base.dart';
import '../mocks.dart';
import '../services/refactoring/legacy/abstract_rename.dart';

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

@reflectiveTest
class UpdateContentTest extends PubPackageAnalysisServerTest {
  Map<File, List<String>> filesErrors = {};
  int serverErrorCount = 0;
  int navigationCount = 0;

  @override
  void processNotification(Notification notification) {
    if (notification.event == ANALYSIS_NOTIFICATION_ERRORS) {
      var decoded = AnalysisErrorsParams.fromNotification(
        notification,
        clientUriConverter: server.uriConverter,
      );
      String format(AnalysisError e) => '${e.location.startLine}: ${e.message}';
      filesErrors[getFile(decoded.file)] = decoded.errors.map(format).toList();
    }
    if (notification.event == ANALYSIS_NOTIFICATION_NAVIGATION) {
      navigationCount++;
    }
    if (notification.event == SERVER_NOTIFICATION_ERROR) {
      serverErrorCount++;
    }
  }

  void test_illegal_ChangeContentOverlay() async {
    // It should be illegal to send a ChangeContentOverlay for a file that
    // doesn't have an overlay yet.
    addTestFile('');
    await setRoots(included: [workspaceRootPath], excluded: []);
    var response = await handleRequest(
      AnalysisUpdateContentParams({
        testFile.path: ChangeContentOverlay([SourceEdit(0, 0, '')]),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    assertResponseFailure(
      response,
      requestId: '0',
      errorCode: RequestErrorCode.INVALID_OVERLAY_CHANGE,
    );
  }

  Future<void> test_invalidFilePathFormat_notAbsolute() async {
    var response = await handleRequest(
      AnalysisUpdateContentParams({
        'test.dart': AddContentOverlay(''),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    expect(
      response,
      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
    );
  }

  Future<void> test_invalidFilePathFormat_notNormalized() async {
    var response = await handleRequest(
      AnalysisUpdateContentParams({
        convertPath('/foo/../bar/test.dart'): AddContentOverlay(''),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    expect(
      response,
      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
    );
  }

  Future<void> test_multiple_contexts() async {
    writePackageConfig(
      workspaceRootPath,
      config:
          PackageConfigFileBuilder()
            ..add(name: 'aaa', rootPath: '$workspaceRootPath/aaa'),
    );

    var aaa = newFile('$workspaceRootPath/aaa/lib/aaa.dart', r'''
void f(int _) {}
''');

    var foo = newFile('$workspaceRootPath/foo/lib/foo.dart', r'''
import 'package:aaa/aaa.dart';
void g() {
  f();
}
''');

    var bar = newFile('$workspaceRootPath/bar/lib/bar.dart', r'''
import 'package:aaa/aaa.dart';
void g() {
  f();
}
''');

    await setRoots(included: [foo.parent.path, bar.parent.path], excluded: []);

    {
      await waitForTasksFinished();
      // Files foo.dart and bar.dart should both have errors, since they both
      // call f() with the wrong number of arguments.
      expect(filesErrors[foo], hasLength(1));
      expect(filesErrors[bar], hasLength(1));
      // Overlay the content of baz.dart to eliminate the errors.
      await handleSuccessfulRequest(
        AnalysisUpdateContentParams({
          aaa.path: AddContentOverlay('void f() {}'),
        }).toRequest('0', clientUriConverter: server.uriConverter),
      );
    }

    {
      await waitForTasksFinished();
      // The overlay should have been propagated to both contexts, causing both
      // foo.dart and bar.dart to be reanalyzed and found to be free of errors.
      expect(filesErrors[foo], isEmpty);
      expect(filesErrors[bar], isEmpty);
    }
  }

  @failingTest
  Future<void> test_overlay_addPreviouslyImported() async {
    // The list of errors doesn't include errors for '/project/target.dart'.
    var project = newFolder('/project');
    await setRoots(included: [project.path], excluded: []);

    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        '/project/main.dart': AddContentOverlay('import "target.dart";'),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    expect(filesErrors, {
      '/project/main.dart': ["1: Target of URI doesn't exist: 'target.dart'."],
      '/project/target.dart': [],
    });

    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        '/project/target.dart': AddContentOverlay('import "none.dart";'),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    expect(filesErrors, {
      '/project/main.dart': ['1: Unused import.'],
      '/project/target.dart': ["1: Target of URI doesn't exist: 'none.dart'."],
      '/project/none.dart': [],
    });
  }

  Future<void> test_overlayOnly() async {
    var a = newFile('$testPackageLibPath/a.dart', '');
    var b = getFile('$testPackageLibPath/b.dart');

    await setRoots(included: [workspaceRootPath], excluded: []);
    await waitForTasksFinished();
    expect(filesErrors[a], isEmpty);
    expect(filesErrors[b], isNull);

    // Add `b.dart` overlay, analyzed.
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        b.path: AddContentOverlay(''),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    expect(filesErrors[a], isEmpty);
    expect(filesErrors[b], isEmpty);

    // Add `b.dart` overlay, analyzed.
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        b.path: RemoveContentOverlay(),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    expect(filesErrors[a], isEmpty);
    // TODO(scheglov): We should get "flush" notification.
    // expect(filesErrors[b], isNull);
  }

  @failingTest
  Future<void> test_sendNoticesAfterNopChange() async {
    // The errors are empty on the last line.
    addTestFile('');
    await setRoots(included: [workspaceRootPath], excluded: []);
    await waitForTasksFinished();
    // add an overlay
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        testFile.path: AddContentOverlay('void f() {} void f() {}'),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    // clear errors and make a no-op change
    filesErrors.clear();
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        testFile.path: ChangeContentOverlay([SourceEdit(5, 1, 'f')]),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    // errors should have been resent
    expect(filesErrors, isNotEmpty);
  }

  @failingTest
  Future<void> test_sendNoticesAfterNopChange_flushedUnit() async {
    // The list of errors is empty on the last line.
    addTestFile('');
    await setRoots(included: [workspaceRootPath], excluded: []);
    await waitForTasksFinished();
    // add an overlay
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        testFile.path: AddContentOverlay('void f() {} void f() {}'),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    // clear errors and make a no-op change
    filesErrors.clear();
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams({
        testFile.path: ChangeContentOverlay([SourceEdit(5, 1, 'f')]),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    await waitForTasksFinished();
    // errors should have been resent
    expect(filesErrors, isNotEmpty);
  }

  Future<void> test_sentToPlugins() async {
    var filePath = convertPath('$testPackageLibPath/a.dart');
    var fileContent = 'import "none.dart";';
    //
    // Add
    //
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams(<String, Object>{
        filePath: AddContentOverlay(fileContent),
      }).toRequest('0', clientUriConverter: server.uriConverter),
    );
    var params = pluginManager.analysisUpdateContentParams!;
    var files = params.files;
    expect(files, hasLength(1));
    var overlay = files[filePath];
    expect(overlay, const TypeMatcher<AddContentOverlay>());
    var addOverlay = overlay as AddContentOverlay;
    expect(addOverlay.content, fileContent);
    //
    // Change
    //
    pluginManager.analysisUpdateContentParams = null;
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams(<String, Object>{
        filePath: ChangeContentOverlay(<SourceEdit>[
          SourceEdit(8, 1, "'"),
          SourceEdit(18, 1, "'"),
        ]),
      }).toRequest('1', clientUriConverter: server.uriConverter),
    );
    params = pluginManager.analysisUpdateContentParams!;
    expect(params, isNotNull);
    files = params.files;
    expect(files, hasLength(1));
    overlay = files[filePath];
    expect(overlay, const TypeMatcher<ChangeContentOverlay>());
    var changeOverlay = overlay as ChangeContentOverlay;
    expect(changeOverlay.edits, hasLength(2));
    //
    // Remove
    //
    pluginManager.analysisUpdateContentParams = null;
    await handleSuccessfulRequest(
      AnalysisUpdateContentParams(<String, Object>{
        filePath: RemoveContentOverlay(),
      }).toRequest('2', clientUriConverter: server.uriConverter),
    );
    params = pluginManager.analysisUpdateContentParams!;
    expect(params, isNotNull);
    files = params.files;
    expect(files, hasLength(1));
    overlay = files[filePath];
    expect(overlay, const TypeMatcher<RemoveContentOverlay>());
  }
}
