// Copyright (c) 2014, 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'
    hide AnalysisOptions;
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:meta/meta.dart';
import 'package:test/test.dart';

import 'mocks.dart';

int findIdentifierLength(String search) {
  var length = 0;
  while (length < search.length) {
    var c = search.codeUnitAt(length);
    if (!(c >= 'a'.codeUnitAt(0) && c <= 'z'.codeUnitAt(0) ||
        c >= 'A'.codeUnitAt(0) && c <= 'Z'.codeUnitAt(0) ||
        c >= '0'.codeUnitAt(0) && c <= '9'.codeUnitAt(0) ||
        c == '_'.codeUnitAt(0))) {
      break;
    }
    length++;
  }
  return length;
}

/// An abstract base for all 'analysis' domain tests.
class AbstractAnalysisTest with ResourceProviderMixin {
  late MockServerChannel serverChannel;
  late TestPluginManager pluginManager;
  late AnalysisServer server;

  final List<GeneralAnalysisService> generalServices =
      <GeneralAnalysisService>[];
  final Map<AnalysisService, List<String>> analysisSubscriptions = {};

  late String projectPath;
  late String testFolder;
  late String testFile;
  late String testCode;

  AbstractAnalysisTest();

  AnalysisOptions get analysisOptions => testDiver.analysisOptions;

  AnalysisDriver get testDiver => server.getAnalysisDriver(testFile)!;

  Future<void> addAnalysisSubscription(
      AnalysisService service, String file) async {
    // add file to subscription
    var files = analysisSubscriptions[service];
    if (files == null) {
      files = <String>[];
      analysisSubscriptions[service] = files;
    }
    files.add(file);
    // set subscriptions
    var request =
        AnalysisSetSubscriptionsParams(analysisSubscriptions).toRequest('0');
    await waitResponse(request);
  }

  String addTestFile(String content) {
    newFile(testFile, content);
    testCode = content;
    return testFile;
  }

  AnalysisServer createAnalysisServer() {
    //
    // Create an SDK in the mock file system.
    //
    var sdkRoot = newFolder('/sdk');
    createMockSdk(
      resourceProvider: resourceProvider,
      root: sdkRoot,
    );

    //
    // Create server
    //
    var options = AnalysisServerOptions();
    return AnalysisServer(
        serverChannel,
        resourceProvider,
        options,
        DartSdkManager(sdkRoot.path),
        CrashReportingAttachmentsBuilder.empty,
        InstrumentationService.NULL_SERVICE);
  }

  /// Creates a project [projectPath].
  Future<void> createProject({Map<String, String>? packageRoots}) async {
    newFolder(projectPath);
    await setRoots(included: [projectPath], excluded: []);
  }

  void doAllDeclarationsTrackerWork() {
    while (server.declarationsTracker!.hasWork) {
      server.declarationsTracker!.doWork();
    }
  }

  /// Returns the offset of [search] in the file at the given [path].
  /// Fails if not found.
  int findFileOffset(String path, String search) {
    var file = getFile(path);
    var code = file.createSource().contents.data;
    var offset = code.indexOf(search);
    expect(offset, isNot(-1), reason: '"$search" in\n$code');
    return offset;
  }

  /// Returns the offset of [search] in [testCode].
  /// Fails if not found.
  int findOffset(String search) {
    var offset = testCode.indexOf(search);
    expect(offset, isNot(-1));
    return offset;
  }

  String modifyTestFile(String content) {
    modifyFile(testFile, content);
    testCode = content;
    return testFile;
  }

  void processNotification(Notification notification) {
    if (notification.event == SERVER_NOTIFICATION_ERROR) {
      fail('${notification.toJson()}');
    }
  }

  Future<Response> setRoots({
    required List<String> included,
    required List<String> excluded,
    bool validateSuccessResponse = true,
  }) async {
    var request = AnalysisSetAnalysisRootsParams(
      included.map(convertPath).toList(),
      excluded.map(convertPath).toList(),
      packageRoots: {},
    ).toRequest('0');
    var response = await waitResponse(request);
    if (validateSuccessResponse) {
      expect(response, isResponseSuccess(request.id));
    }
    return response;
  }

  @mustCallSuper
  void setUp() async {
    serverChannel = MockServerChannel();
    projectPath = convertPath('/project');
    testFolder = convertPath('/project/bin');
    testFile = convertPath('/project/bin/test.dart');
    pluginManager = TestPluginManager();
    server = createAnalysisServer();
    server.pluginManager = pluginManager;
    serverChannel.notifications.listen(processNotification);
  }

  @mustCallSuper
  void tearDown() {
    server.done();
  }

  /// Returns a [Future] that completes when the server's analysis is complete.
  Future<void> waitForTasksFinished() {
    return server.onAnalysisComplete;
  }

  /// Completes with a successful [Response] for the given [request].
  /// Otherwise fails.
  Future<Response> waitResponse(Request request,
      {bool throwOnError = true}) async {
    return serverChannel.sendRequest(request, throwOnError: throwOnError);
  }
}
