// Copyright (c) 2022, 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/src/analytics/analytics_manager.dart';
import 'package:analysis_server/src/legacy_analysis_server.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
import 'package:analysis_server/src/services/user_prompts/dart_fix_prompt_manager.dart';
import 'package:analysis_server/src/session_logger/session_logger.dart';
import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/dart/analysis/analysis_options.dart' as analysis;
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:analyzer/source/source_range.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/platform.dart';
import 'package:analyzer/src/test_utilities/test_code_format.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_testing/configuration_files_mixin.dart';
import 'package:analyzer_testing/experiments/experiments.dart';
import 'package:analyzer_testing/mock_packages/mock_packages.dart';
import 'package:analyzer_testing/resource_provider_mixin.dart';
import 'package:analyzer_testing/utilities/extensions/resource_provider.dart';
import 'package:analyzer_testing/utilities/utilities.dart';
import 'package:meta/meta.dart';
import 'package:test/test.dart';
import 'package:unified_analytics/unified_analytics.dart';

import 'constants.dart';
import 'mocks.dart';
import 'utils/message_scheduler_test_view.dart';

class BlazeWorkspaceAnalysisServerTest extends ContextResolutionTest {
  String get myPackageLibPath => '$myPackageRootPath/lib';

  String get myPackageRootPath => '$workspaceRootPath/dart/my';

  Folder get workspaceRoot => getFolder(workspaceRootPath);

  String get workspaceRootPath => '/workspace';

  @override
  void createDefaultFiles() {
    newFile('$workspaceRootPath/${file_paths.blazeWorkspaceMarker}', '');
  }
}

abstract class ContextResolutionTest with ResourceProviderMixin {
  /// The byte store that is reused between tests. This allows reusing all
  /// unlinked and linked summaries for SDK, so that tests run much faster.
  /// However nothing is preserved between Dart VM runs, so changes to the
  /// implementation are still fully verified.
  static final MemoryByteStore _sharedByteStore = MemoryByteStore();

  /// The next ID to use in a request to the server.
  var nextRequestId = 0;

  MemoryByteStore _byteStore = _sharedByteStore;

  late final TestPluginManager pluginManager = TestPluginManager(
    resourceProvider,
  );
  late final MockServerChannel serverChannel;
  MessageSchedulerTestView? testView;
  late final LegacyAnalysisServer server;

  DartFixPromptManager? dartFixPromptManager;

  final List<GeneralAnalysisService> _analysisGeneralServices = [];
  final Map<AnalysisService, List<String>> _analysisFileSubscriptions = {};

  void Function(Notification)? notificationListener;

  bool _hasSetRoots = false;

  String get dartSdkPath => sdkRoot.path;

  /// Whether analysis roots have been set for this first time.
  ///
  /// Used as a safety check to ensure tests that send client capabilities do
  /// so before this, because otherwise the capabilities might not apply during
  /// initial analysis.
  bool get hasSetRoots => _hasSetRoots;

  bool get retainDataForTesting => false;

  Folder get sdkRoot => newFolder('/sdk');

  Future<void> addGeneralAnalysisSubscription(
    GeneralAnalysisService service,
  ) async {
    _analysisGeneralServices.add(service);
    await _setGeneralAnalysisSubscriptions();
  }

  void assertResponseFailure(
    Response response, {
    required String requestId,
    required RequestErrorCode errorCode,
  }) {
    expect(response, isResponseFailure(requestId, errorCode));
  }

  void createDefaultFiles() {}

  Future<Response> handleRequest(Request request) async {
    return await serverChannel.simulateRequestFromClient(request);
  }

  /// Validates that the given [request] is handled successfully.
  Future<Response> handleSuccessfulRequest(Request request) async {
    var response = await handleRequest(request);
    expect(response, isResponseSuccess(request.id));
    return response;
  }

  void processNotification(Notification notification) {
    notificationListener?.call(notification);
  }

  Future<void> removeGeneralAnalysisSubscription(
    GeneralAnalysisService service,
  ) async {
    _analysisGeneralServices.remove(service);
    await _setGeneralAnalysisSubscriptions();
  }

  void setPriorityFiles(List<File> files) {
    handleSuccessfulRequest(
      AnalysisSetPriorityFilesParams(files.map((e) => e.path).toList())
          .toRequest(
            '${nextRequestId++}',
            clientUriConverter: server.uriConverter,
          ),
    );
  }

  Future<void> setPriorityFiles2(List<File> files) async {
    await handleSuccessfulRequest(
      AnalysisSetPriorityFilesParams(files.map((e) => e.path).toList())
          .toRequest(
            '${nextRequestId++}',
            clientUriConverter: server.uriConverter,
          ),
    );
  }

  Future<void> setRoots({
    required List<String> included,
    required List<String> excluded,
  }) async {
    _hasSetRoots = true;

    var includedConverted = included.map(convertPath).toList();
    var excludedConverted = excluded.map(convertPath).toList();
    await handleSuccessfulRequest(
      AnalysisSetAnalysisRootsParams(
        includedConverted,
        excludedConverted,
        packageRoots: {},
      ).toRequest(
        '${nextRequestId++}',
        clientUriConverter: server.uriConverter,
      ),
    );
  }

  @mustCallSuper
  void setUp() {
    serverChannel = MockServerChannel(printMessages: debugPrintCommunication);

    createMockSdk(resourceProvider: resourceProvider, root: sdkRoot);

    createDefaultFiles();

    serverChannel.notifications.listen(processNotification);

    testView = retainDataForTesting ? MessageSchedulerTestView() : null;
    server = LegacyAnalysisServer(
      serverChannel,
      resourceProvider,
      AnalysisServerOptions(),
      DartSdkManager(sdkRoot.path),
      AnalyticsManager(NoOpAnalytics()),
      CrashReportingAttachmentsBuilder.empty,
      InstrumentationService.NULL_SERVICE,
      SessionLogger(),
      dartFixPromptManager: dartFixPromptManager,
      providedByteStore: _byteStore,
      pluginManager: pluginManager,
      messageSchedulerListener: testView,
    );

    server.completionState.budgetDuration = const Duration(seconds: 30);
  }

  Future<void> tearDown() async {
    await server.shutdown();
  }

  /// Returns a [Future] that completes when the server's analysis is complete.
  Future<void> waitForTasksFinished() async {
    await pumpEventQueue(times: 1 << 10);
    await server.onAnalysisComplete;
  }

  Future<void> _setGeneralAnalysisSubscriptions() async {
    await handleSuccessfulRequest(
      AnalysisSetGeneralSubscriptionsParams(_analysisGeneralServices).toRequest(
        '${nextRequestId++}',
        clientUriConverter: server.uriConverter,
      ),
    );
  }
}

class PubPackageAnalysisServerTest extends ContextResolutionTest
    with MockPackagesMixin, ConfigurationFilesMixin {
  late String pubspecFilePath = pathContext.normalize(
    resourceProvider.convertPath('$testPackageRootPath/pubspec.yaml'),
  );

  late TestCode parsedTestCode;

  final String testPackageName = 'test';

  /// Return a list of the experimental features that are to be enabled for
  /// tests in this class.
  List<Feature> get experimentalFeatures => experimentalFeaturesForTests;

  /// The path that is not in [workspaceRootPath], contains external packages.
  @override
  String get packagesRootPath => resourceProvider.convertPath('/packages');

  List<TestCodePosition> get parsedPositions => parsedTestCode.positions;

  TestCodeRange get parsedRange => parsedTestCode.range;

  List<TestCodeRange> get parsedRanges => parsedTestCode.ranges;

  SourceRange get parsedSourceRange => parsedTestCode.range.sourceRange;

  File get testFile => getFile(testFilePath);

  analysis.AnalysisOptions get testFileAnalysisOptions {
    var analysisDriver = server.getAnalysisDriver(testFile.path)!;
    return analysisDriver.getAnalysisOptionsForFile(testFile);
  }

  String get testFileContent => testFile.readAsStringSync();

  String get testFilePath =>
      resourceProvider.convertPath('$testPackageLibPath/test.dart');

  String get testPackageLibPath => '$testPackageRootPath/lib';

  Folder get testPackageRoot => getFolder(testPackageRootPath);

  @override
  String get testPackageRootPath => '$workspaceRootPath/$testPackageName';

  String get testPackageTestPath => '$testPackageRootPath/test';

  Folder get workspaceRoot => getFolder(workspaceRootPath);

  String get workspaceRootPath => '/home';

  Future<void> addAnalysisSubscription(
    AnalysisService service,
    File file,
  ) async {
    (_analysisFileSubscriptions[service] ??= []).add(file.path);
    await handleSuccessfulRequest(
      AnalysisSetSubscriptionsParams(_analysisFileSubscriptions).toRequest(
        '${nextRequestId++}',
        clientUriConverter: server.uriConverter,
      ),
    );
  }

  // TODO(scheglov): rename
  void addTestFile(String content) {
    parsedTestCode = TestCode.parseNormalized(content);
    newFile(testFilePath, parsedTestCode.code);
  }

  @override
  void createDefaultFiles() {
    writeTestPackageConfig2();
    writeTestPackagePubspecYamlFile('name: $testPackageName');

    writeTestPackageAnalysisOptionsFile(
      analysisOptionsContent(experimentalFeatures: experimentalFeatures),
    );
  }

  /// Deletes the analysis options YAML file at [testPackageRootPath].
  void deleteTestPackageAnalysisOptionsFile() {
    var path = join(testPackageRootPath, file_paths.analysisOptionsYaml);
    deleteFile(path);
  }

  /// Deletes the `package_config.json` file at [testPackageRootPath].
  void deleteTestPackageConfigJsonFile() {
    var filePath = join(
      testPackageRootPath,
      file_paths.dotDartTool,
      file_paths.packageConfigJson,
    );
    deleteFile(filePath);
  }

  /// Returns the offset of [search] in [testFileContent].
  /// Fails if not found.
  // TODO(scheglov): Rename it.
  int findOffset(String search) {
    return offsetInFile(testFile, search);
  }

  void modifyTestFile(String content) {
    modifyFile2(testFile, content);
  }

  @override
  File newFile(String path, String content) {
    content = normalizeNewlinesForPlatform(content);
    return super.newFile(path, content);
  }

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

  /// Call this method if the test needs to use the empty byte store, without
  /// any information cached.
  void useEmptyByteStore() {
    _byteStore = MemoryByteStore();
  }

  void writeTestPackageAnalysisOptionsFile(String content) {
    newAnalysisOptionsYamlFile(testPackageRootPath, content);
  }

  void writeTestPackagePubspecYamlFile(String content) {
    newPubspecYamlFile(testPackageRootPath, content);
  }
}
