// 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/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/handler/legacy/legacy_handler.dart';
import 'package:analysis_server/src/legacy_analysis_server.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/plugin/result_converter.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/request_handler_mixin.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/fix/analysis_options/fix_generator.dart';
import 'package:analysis_server/src/services/correction/fix/pubspec/fix_generator.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/dart/analysis/results.dart' as engine;
import 'package:analyzer/src/exception/exception.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/pubspec/pubspec_validator.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:yaml/yaml.dart';

/// The handler for the `edit.getFixes` request.
class EditGetFixesHandler extends LegacyHandler
    with RequestHandlerMixin<LegacyAnalysisServer> {
  /// Initialize a newly created handler to be able to service requests for the
  /// [server].
  EditGetFixesHandler(super.server, super.request, super.cancellationToken);

  @override
  Future<void> handle() async {
    var params = EditGetFixesParams.fromRequest(request);
    var file = params.file;
    var offset = params.offset;

    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
      return;
    }

    if (!server.isAnalyzed(file)) {
      server.sendResponse(Response.getFixesInvalidFile(request));
      return;
    }

    //
    // Allow plugins to start computing fixes.
    //
    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
    var requestParams = plugin.EditGetFixesParams(file, offset);
    var driver = server.getAnalysisDriver(file);
    if (driver == null) {
      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
    } else {
      pluginFutures = server.pluginManager.broadcastRequest(
        requestParams,
        contextRoot: driver.analysisContext!.contextRoot,
      );
    }
    //
    // Compute fixes associated with server-generated errors.
    //
    List<AnalysisErrorFixes>? errorFixesList;
    while (errorFixesList == null) {
      try {
        errorFixesList = await _computeServerErrorFixes(request, file, offset);
      } on InconsistentAnalysisException {
        // Loop around to try again to compute the fixes.
      }
    }
    //
    // Add the fixes produced by plugins to the server-generated fixes.
    //
    var responses =
        await waitForResponses(pluginFutures, requestParameters: requestParams);
    server.requestStatistics?.addItemTimeNow(request, 'pluginResponses');
    var converter = ResultConverter();
    for (var response in responses) {
      var result = plugin.EditGetFixesResult.fromResponse(response);
      errorFixesList
          .addAll(result.fixes.map(converter.convertAnalysisErrorFixes));
    }
    //
    // Send the response.
    //
    sendResult(EditGetFixesResult(errorFixesList));
  }

  /// Compute and return the fixes associated with server-generated errors in
  /// analysis options files.
  Future<List<AnalysisErrorFixes>> _computeAnalysisOptionsFixes(
      String file, int offset) async {
    var errorFixesList = <AnalysisErrorFixes>[];
    var resourceProvider = server.resourceProvider;
    var optionsFile = resourceProvider.getFile(file);
    var content = _safelyRead(optionsFile);
    if (content == null) {
      return errorFixesList;
    }
    var driver = server.getAnalysisDriver(file);
    if (driver == null) {
      return errorFixesList;
    }
    await driver.applyPendingFileChanges();
    var session = driver.currentSession;
    var sourceFactory = driver.sourceFactory;
    var errors = analyzeAnalysisOptions(
      optionsFile.createSource(),
      content,
      sourceFactory,
      session.analysisContext.contextRoot.root.path,
    );
    var options = _getOptions(sourceFactory, content);
    if (options == null) {
      return errorFixesList;
    }
    for (var error in errors) {
      var generator = AnalysisOptionsFixGenerator(
          resourceProvider, error, content, options);
      var fixes = await generator.computeFixes();
      if (fixes.isNotEmpty) {
        fixes.sort(Fix.compareFixes);
        var lineInfo = LineInfo.fromContent(content);
        var result = engine.ErrorsResultImpl(
          session: session,
          path: file,
          uri: Uri.file(file),
          lineInfo: lineInfo,
          isAugmentation: false,
          isLibrary: true,
          isPart: false,
          errors: errors,
        );
        var serverError = newAnalysisError_fromEngine(result, error);
        var errorFixes = AnalysisErrorFixes(serverError);
        errorFixesList.add(errorFixes);
        for (var fix in fixes) {
          errorFixes.fixes.add(fix.change);
        }
      }
    }
    return errorFixesList;
  }

  /// Compute and return the fixes associated with server-generated errors in
  /// Dart files.
  Future<List<AnalysisErrorFixes>> _computeDartFixes(
      Request request, String file, int offset) async {
    var errorFixesList = <AnalysisErrorFixes>[];
    var result = await server.getResolvedUnit(file);
    server.requestStatistics?.addItemTimeNow(request, 'resolvedUnit');
    if (result != null) {
      var lineInfo = result.lineInfo;
      var requestLine = lineInfo.getLocation(offset).lineNumber;
      for (var error in result.errors) {
        var errorLine = lineInfo.getLocation(error.offset).lineNumber;
        if (errorLine == requestLine) {
          var workspace = DartChangeWorkspace(
            await server.currentSessions,
          );
          var context = DartFixContextImpl(
              server.instrumentationService, workspace, result, error);

          List<Fix> fixes;
          try {
            fixes = await DartFixContributor().computeFixes(context);
          } on InconsistentAnalysisException {
            fixes = [];
          } catch (exception, stackTrace) {
            var parametersFile = '''
offset: $offset
error: $error
error.errorCode: ${error.errorCode}
''';
            throw CaughtExceptionWithFiles(exception, stackTrace, {
              file: result.content,
              'parameters': parametersFile,
            });
          }

          if (fixes.isNotEmpty) {
            fixes.sort(Fix.compareFixes);
            var serverError = newAnalysisError_fromEngine(result, error);
            var errorFixes = AnalysisErrorFixes(serverError);
            errorFixesList.add(errorFixes);
            for (var fix in fixes) {
              errorFixes.fixes.add(fix.change);
            }
          }
        }
      }
    }
    server.requestStatistics?.addItemTimeNow(request, 'computedFixes');
    return errorFixesList;
  }

  /// Compute and return the fixes associated with server-generated errors in
  /// pubspec.yaml files.
  Future<List<AnalysisErrorFixes>> _computePubspecFixes(
      String file, int offset) async {
    var errorFixesList = <AnalysisErrorFixes>[];
    var resourceProvider = server.resourceProvider;
    var pubspecFile = resourceProvider.getFile(file);
    var content = _safelyRead(pubspecFile);
    if (content == null) {
      return errorFixesList;
    }
    var session = await server.getAnalysisSession(file);
    if (session == null) {
      return errorFixesList;
    }
    YamlDocument document;
    try {
      document = loadYamlDocument(content);
    } catch (exception) {
      return errorFixesList;
    }
    var yamlContent = document.contents;
    if (yamlContent is! YamlMap) {
      yamlContent = YamlMap();
    }
    var validator =
        PubspecValidator(resourceProvider, pubspecFile.createSource());
    var errors = validator.validate(yamlContent.nodes);
    for (var error in errors) {
      var generator =
          PubspecFixGenerator(resourceProvider, error, content, document);
      var fixes = await generator.computeFixes();
      if (fixes.isNotEmpty) {
        fixes.sort(Fix.compareFixes);
        var lineInfo = LineInfo.fromContent(content);
        var result = engine.ErrorsResultImpl(
          session: session,
          path: file,
          uri: Uri.file(file),
          lineInfo: lineInfo,
          isAugmentation: false,
          isLibrary: true,
          isPart: false,
          errors: errors,
        );
        var serverError = newAnalysisError_fromEngine(result, error);
        var errorFixes = AnalysisErrorFixes(serverError);
        errorFixesList.add(errorFixes);
        for (var fix in fixes) {
          errorFixes.fixes.add(fix.change);
        }
      }
    }
    return errorFixesList;
  }

  /// Compute and return the fixes associated with server-generated errors.
  Future<List<AnalysisErrorFixes>> _computeServerErrorFixes(
      Request request, String file, int offset) async {
    var pathContext = server.resourceProvider.pathContext;
    if (file_paths.isDart(pathContext, file)) {
      return _computeDartFixes(request, file, offset);
    } else if (file_paths.isAnalysisOptionsYaml(pathContext, file)) {
      return _computeAnalysisOptionsFixes(file, offset);
    } else if (file_paths.isPubspecYaml(pathContext, file)) {
      return _computePubspecFixes(file, offset);
    }
    return <AnalysisErrorFixes>[];
  }

  YamlMap? _getOptions(SourceFactory sourceFactory, String content) {
    var optionsProvider = AnalysisOptionsProvider(sourceFactory);
    try {
      return optionsProvider.getOptionsFromString(content);
    } on OptionsFormatException {
      return null;
    }
  }

  /// Return the contents of the [file], or `null` if the file does not exist or
  /// cannot be read.
  String? _safelyRead(File file) {
    try {
      return file.readAsStringSync();
    } on FileSystemException {
      return null;
    }
  }
}
