// 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 'dart:async';

import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Position;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'server_abstract.dart';

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

@reflectiveTest
class DocumentChangesTest extends AbstractLspAnalysisServerTest {
  String get content => '''
class Foo {
  String get bar => 'baz';
}
''';

  String get contentAfterUpdate => '''
class Bar {
  String get bar => 'updated';
}
''';

  Future<void> test_documentChange_notifiesPlugins() async {
    if (!AnalysisServer.supportsPlugins) return;
    await _initializeAndOpen();
    await changeFile(2, mainFileUri, [
      TextDocumentContentChangeEvent.t1(
        TextDocumentContentChangePartial(
          range: Range(
            start: Position(line: 0, character: 6),
            end: Position(line: 0, character: 9),
          ),
          text: 'Bar',
        ),
      ),
      TextDocumentContentChangeEvent.t1(
        TextDocumentContentChangePartial(
          range: Range(
            start: Position(line: 1, character: 21),
            end: Position(line: 1, character: 24),
          ),
          text: 'updated',
        ),
      ),
    ]);

    var notifiedChanges =
        pluginManager.analysisUpdateContentParams!.files[mainFilePath]
            as ChangeContentOverlay;

    expect(
      applySequenceOfEdits(content, notifiedChanges.edits),
      contentAfterUpdate,
    );
  }

  Future<void> test_documentChange_updatesOverlay() async {
    await _initializeAndOpen();
    await changeFile(2, mainFileUri, [
      TextDocumentContentChangeEvent.t1(
        TextDocumentContentChangePartial(
          range: Range(
            start: Position(line: 0, character: 6),
            end: Position(line: 0, character: 9),
          ),
          text: 'Bar',
        ),
      ),
      TextDocumentContentChangeEvent.t1(
        TextDocumentContentChangePartial(
          range: Range(
            start: Position(line: 1, character: 21),
            end: Position(line: 1, character: 24),
          ),
          text: 'updated',
        ),
      ),
    ]);

    expect(server.resourceProvider.hasOverlay(mainFilePath), isTrue);
    expect(
      server.resourceProvider.getFile(mainFilePath).readAsStringSync(),
      equals(contentAfterUpdate),
    );
  }

  Future<void> test_documentClose_deletesOverlay() async {
    await _initializeAndOpen();
    await closeFile(mainFileUri);

    expect(server.resourceProvider.hasOverlay(mainFilePath), isFalse);
  }

  Future<void> test_documentClose_notifiesPlugins() async {
    if (!AnalysisServer.supportsPlugins) return;
    await _initializeAndOpen();
    await closeFile(mainFileUri);

    expect(
      pluginManager.analysisUpdateContentParams!.files,
      equals({mainFilePath: RemoveContentOverlay()}),
    );
  }

  Future<void>
  test_documentOpen_addsOverlayOnlyToDriver_onlyIfInsideRoots() async {
    // Ensures that opening a file doesn't add it to the driver if it's outside
    // of the drivers root.
    var fileInsideRootPath = mainFilePath;
    var fileOutsideRootPath = convertPath('/home/unrelated/main.dart');
    await initialize();
    await openFile(pathContext.toUri(fileInsideRootPath), content);
    await openFile(pathContext.toUri(fileOutsideRootPath), content);

    // Expect both files return the same driver
    var driverForInside = server.getAnalysisDriver(fileInsideRootPath)!;
    var driverForOutside = server.getAnalysisDriver(fileOutsideRootPath)!;
    expect(driverForInside, equals(driverForOutside));
    // But that only the file inside the root was added.
    expect(driverForInside.addedFiles, contains(fileInsideRootPath));
    expect(driverForInside.addedFiles, isNot(contains(fileOutsideRootPath)));
  }

  Future<void> test_documentOpen_contentChanged_analysis() async {
    failTestOnErrorDiagnostic = false;

    const content = '// original content';
    const newContent = 'new content'; // triggers diagnostic
    newFile(mainFilePath, content);

    await initialize();
    await initialAnalysis;

    await openFile(mainFileUri, newContent);
    await pumpEventQueue(times: 50000);

    // Expect diagnostics, because changing the content will have triggered
    // analysis.
    expect(diagnostics[mainFileUri], isNotEmpty);
  }

  Future<void> test_documentOpen_contentUnchanged_noAnalysis() async {
    const content = '// original content';
    newFile(mainFilePath, content);

    await initialize();
    await initialAnalysis;

    await openFile(mainFileUri, content);
    await pumpEventQueue(times: 5000);

    // Expect no diagnostics because the file didn't actually change content
    // when the overlay was created, so it should not have triggered analysis.
    expect(diagnostics[mainFileUri], isNull);
  }

  Future<void> test_documentOpen_createsOverlay() async {
    await _initializeAndOpen();

    expect(server.resourceProvider.hasOverlay(mainFilePath), isTrue);
    expect(
      server.resourceProvider.getFile(mainFilePath).readAsStringSync(),
      equals(content),
    );
  }

  /// Verify that calling open/close repeatedly produces no errors and ends
  /// in the closed state.
  Future<void> test_documentOpen_documentClose_repeatedly_endClosed() async {
    await initialize(
      // This forces roots to be rebuilt when the files open/close which
      // increases the workload and makes any `await` in processing open/close
      // files more likely to trigger the failure.
      initializationOptions: {'onlyAnalyzeProjectsWithOpenFiles': true},
    );

    await Future.wait([
      for (var i = 0; i < 100; i++) ...[
        openFile(mainFileUri, content),
        closeFile(mainFileUri),
      ],
    ]);

    expect(server.resourceProvider.hasOverlay(mainFilePath), isFalse);
  }

  /// Verify that calling open/close repeatedly produces no errors and ends
  /// in the open state if the last entry was open.
  Future<void> test_documentOpen_documentClose_repeatedly_endOpen() async {
    await initialize(
      // This forces roots to be rebuilt when the files open/close which
      // increases the workload and makes any `await` in processing open/close
      // files more likely to trigger the failure.
      initializationOptions: {'onlyAnalyzeProjectsWithOpenFiles': true},
    );

    await Future.wait([
      for (var i = 0; i < 100; i++) ...[
        openFile(mainFileUri, content),
        closeFile(mainFileUri),
      ],
      openFile(mainFileUri, content),
    ]);
    await pumpEventQueue(times: 50000);
    expect(server.resourceProvider.hasOverlay(mainFilePath), isTrue);
  }

  /// Tests that deleting a file does not clear diagnostics while there's an
  /// overlay, and that removing the overlay later clears the diagnostics.
  ///
  /// https://github.com/dart-lang/sdk/issues/53475
  Future<void> test_documentOpen_fileDeleted_documentClosed() async {
    failTestOnErrorDiagnostic = false;

    const content = 'error';
    newFile(mainFilePath, content);

    // Expect diagnostics after initial analysis because file has invalid
    // content.
    await initialize();
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics after opening the file with the same contents.
    await openFile(mainFileUri, content);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics after deleting the file because the overlay is still
    // active.
    deleteFile(mainFilePath);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics to be removed after we close the file (which removes
    // the overlay).
    await closeFile(mainFileUri);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isEmpty);
  }

  /// Tests that deleting and re-creating a file while an overlay is active
  /// keeps the diagnotics when the overlay is then removed, then removes them
  /// when the file is deleted.
  ///
  /// https://github.com/dart-lang/sdk/issues/53475
  Future<void>
  test_documentOpen_fileDeleted_fileCreated_documentClosed_fileDeleted() async {
    failTestOnErrorDiagnostic = false;

    const content = 'error';
    newFile(mainFilePath, content);

    // Expect diagnostics after initial analysis because file has invalid
    // content.
    await initialize();
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics after opening the file with the same contents.
    await openFile(mainFileUri, content);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics after deleting the file because the overlay is still
    // active.
    deleteFile(mainFilePath);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics remain after re-creating the file (the overlay is still
    // active).
    newFile(mainFilePath, content);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Expect diagnostics remain after we close the file because the file still
    //exists on disk.
    await closeFile(mainFileUri);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isNotEmpty);

    // Finally, expect deleting the file clears the diagnostics.
    deleteFile(mainFilePath);
    await pumpEventQueue(times: 5000);
    expect(diagnostics[mainFileUri], isEmpty);
  }

  Future<void> test_documentOpen_notifiesPlugins() async {
    if (!AnalysisServer.supportsPlugins) return;
    await _initializeAndOpen();

    expect(
      pluginManager.analysisUpdateContentParams!.files,
      equals({mainFilePath: AddContentOverlay(content)}),
    );
  }

  /// Verifies the fix for a race condition where an overlay would not be
  /// processed if the file was created on disk before the overlay was processed
  /// (but the watch event had also not yet been processed).
  ///
  /// https://github.com/dart-lang/sdk/issues/51159
  Future<void> test_documentOpen_processesOverlay_dartSdk_issue51159() async {
    failTestOnErrorDiagnostic = false;

    var binFolder = convertPath(join(projectFolderPath, 'bin'));
    var binMainFilePath = convertPath(join(binFolder, 'main.dart'));
    var binMainFileUri = pathContext.toUri(binMainFilePath);
    var fooFilePath = convertPath(join(binFolder, 'foo.dart'));
    var fooUri = pathContext.toUri(fooFilePath);

    const binMainContent = '''
import 'foo.dart';

Foo? f;
''';
    const fooContent = '''
class Foo {}
''';

    newFolder(binFolder);
    newFile(binMainFilePath, binMainContent);

    await initialize();
    await initialAnalysis;

    // Expect diagnostics because 'foo.dart' doesn't exist.
    expect(diagnostics[binMainFileUri], isNotEmpty);

    // Create the file and _immediately_ open it, so the file exists when the
    // overlay is created, even though the watcher event has not been processed.
    newFile(fooFilePath, fooContent);
    await Future.wait([
      openFile(fooUri, fooContent),
      waitForAnalysisComplete(),
    ]);

    // Expect the diagnostics have gone.
    expect(diagnostics[binMainFileUri], isEmpty);
  }

  Future<void> test_documentOpen_setsPriorityFileIfEarly() async {
    setConfigurationSupport();

    // When initializing with config support, the server will call back to the client
    // which can delay analysis roots being configured. This can result in files
    // being opened before analysis roots are set which has previously caused the
    // files not to be marked as priority on the created drivers.
    // https://github.com/Dart-Code/Dart-Code/issues/2438
    // https://github.com/dart-lang/sdk/issues/42994

    // Initialize the server, but delay providing the configuration until after
    // we've opened the file.
    var completer = Completer<void>();

    // Send the initialize request but do not await it.
    var initResponse = initialize();

    // When asked for config, delay the response until we have sent the openFile notification.
    var config = provideConfig(
      () => initResponse,
      completer.future.then((_) => {'dart.foo': false}),
    );

    // Wait for initialization to finish, open the file, then allow config to complete.
    await initResponse;
    await openFile(mainFileUri, content);
    completer.complete();
    await config;
    await pumpEventQueue(times: 5000);

    // Ensure the opened file is in the priority list.
    expect(
      server.getAnalysisDriver(mainFilePath)!.priorityFiles,
      equals([mainFilePath]),
    );
  }

  Future<void> _initializeAndOpen() async {
    await initialize();
    await openFile(mainFileUri, content);
  }
}
