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

import 'package:analysis_server/lsp_protocol/protocol.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../tool/lsp_spec/matchers.dart';
import 'server_abstract.dart';

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

@reflectiveTest
class ServerTest extends AbstractLspAnalysisServerTest {
  Future<void> test_capturesLatency_afterStartup() async {
    await initialize(includeClientRequestTime: true);
    await openFile(mainFileUri, '');
    await expectLater(
      getHover(mainFileUri, startOfDocPos),
      completes,
    );
    expect(server.performanceAfterStartup!.latencyCount, isPositive);
  }

  Future<void> test_capturesLatency_startup() async {
    await initialize(includeClientRequestTime: true);
    expect(server.performanceDuringStartup.latencyCount, isPositive);
  }

  Future<void> test_capturesRequestPerformance() async {
    await initialize(includeClientRequestTime: true);
    await openFile(mainFileUri, '');
    await expectLater(
      getHover(mainFileUri, startOfDocPos),
      completes,
    );
    final performanceItems = server.recentPerformance.requests.items;
    final hoverItems = performanceItems.where(
        (item) => item.operation == Method.textDocument_hover.toString());
    expect(hoverItems, hasLength(1));
  }

  Future<void> test_inconsistentStateError() async {
    await initialize(
      // Error is expected and checked below.
      failTestOnAnyErrorNotification: false,
    );
    await openFile(mainFileUri, '');
    // Attempt to make an illegal modification to the file. This indicates the
    // client and server are out of sync and we expect the server to shut down.
    final error = await expectErrorNotification(() async {
      await changeFile(222, mainFileUri, [
        Either2<TextDocumentContentChangeEvent1,
                TextDocumentContentChangeEvent2>.t1(
            TextDocumentContentChangeEvent1(
                range: Range(
                    start: Position(line: 99, character: 99),
                    end: Position(line: 99, character: 99)),
                text: ' ')),
      ]);
    });

    expect(error, isNotNull);
    expect(error.message, contains('Invalid line'));

    // Wait for up to 10 seconds for the server to shutdown.
    await server.exited.timeout(const Duration(seconds: 10));
  }

  Future<void> test_path_doesNotExist() async {
    final missingFileUri = Uri.file(join(projectFolderPath, 'missing.dart'));
    await initialize();
    await expectLater(
      getHover(missingFileUri, startOfDocPos),
      throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
          message: 'File does not exist')),
    );
  }

  Future<void> test_path_invalidFormat() async {
    await initialize();
    await expectLater(
      // Add some invalid path characters to the end of a valid file:// URI.
      formatDocument(mainFileUri.toString() + r'***###\\\///:::.dart'),
      throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
          message: 'File URI did not contain a valid file path')),
    );
  }

  Future<void> test_path_missingDriveLetterWindows() async {
    // This test is only valid on Windows, as a URI in the format:
    //    file:///foo/bar.dart
    // is valid for non-Windows platforms, but not valid on Windows as it does
    // not have a drive letter.
    if (!Platform.isWindows) {
      return;
    }
    final missingDriveLetterFileUri = Uri.file('/foo/bar.dart');
    await initialize();
    await expectLater(
      getHover(missingDriveLetterFileUri, startOfDocPos),
      // The Uri.file() above translates to a non-file:// URI of just 'a/b.dart'
      // so will get the not-file-scheme error message.
      throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
          message: 'URI was not an absolute file path (missing drive letter)')),
    );
  }

  Future<void> test_path_notFileScheme() async {
    final relativeFileUri = Uri(scheme: 'foo', path: '/a/b.dart');
    await initialize();
    await expectLater(
      getHover(relativeFileUri, startOfDocPos),
      throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
          message: 'URI was not a valid file:// URI')),
    );
  }

  Future<void> test_path_relative() async {
    final relativeFileUri = Uri.file('a/b.dart');
    await initialize();
    await expectLater(
      getHover(relativeFileUri, startOfDocPos),
      // The Uri.file() above translates to a non-file:// URI of just 'a/b.dart'
      // so will get the not-file-scheme error message.
      throwsA(isResponseError(ServerErrorCodes.InvalidFilePath,
          message: 'URI was not a valid file:// URI')),
    );
  }

  Future<void> test_shutdown_initialized() async {
    await initialize();
    final response = await sendShutdown();
    expect(response, isNull);
  }

  Future<void> test_shutdown_uninitialized() async {
    final response = await sendShutdown();
    expect(response, isNull);
  }

  Future<void> test_unknownNotifications_logError() async {
    await initialize(
      // Error is expected and checked below.
      failTestOnAnyErrorNotification: false,
    );

    final notification =
        makeNotification(Method.fromJson(r'some/randomNotification'), null);

    final notificationParams = await expectErrorNotification(
      () => channel.sendNotificationToServer(notification),
    );
    expect(notificationParams, isNotNull);
    expect(
      notificationParams.message,
      contains('Unknown method some/randomNotification'),
    );
  }

  Future<void> test_unknownOptionalNotifications_silentlyDropped() async {
    await initialize();
    final notification =
        makeNotification(Method.fromJson(r'$/randomNotification'), null);
    final firstError = errorNotificationsFromServer.first;
    channel.sendNotificationToServer(notification);

    // Wait up to 1sec to ensure no error/log notifications were sent back.
    var didTimeout = false;
    final notificationFromServer =
        await firstError.then<NotificationMessage?>((error) => error).timeout(
      const Duration(seconds: 1),
      onTimeout: () {
        didTimeout = true;
        return null;
      },
    );

    expect(notificationFromServer, isNull);
    expect(didTimeout, isTrue);
  }

  Future<void> test_unknownOptionalRequest_rejected() async {
    await initialize();
    final request = makeRequest(Method.fromJson(r'$/randomRequest'), null);
    final response = await channel.sendRequestToServer(request);
    expect(response.id, equals(request.id));
    expect(response.error, isNotNull);
    expect(response.error!.code, equals(ErrorCodes.MethodNotFound));
    expect(response.result, isNull);
  }

  Future<void> test_unknownRequest_rejected() async {
    await initialize();
    final request = makeRequest(Method.fromJson('randomRequest'), null);
    final response = await channel.sendRequestToServer(request);
    expect(response.id, equals(request.id));
    expect(response.error, isNotNull);
    expect(response.error!.code, equals(ErrorCodes.MethodNotFound));
    expect(response.result, isNull);
  }
}
