// Copyright (c) 2020, 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/src/computer/computer_documentation.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as path;

/// Client configuration for Dart CodeLenses.
///
/// Defaults are set per-CodeLens but the user can override these by enabling
/// all, disabling all, or setting their own preferences.
///
/// ```js
/// "dart.codeLens": true, // Enables all CodeLens
///
/// "dart.codeLens": false, // Disables all CodeLens
///
/// "dart.codeLens": {
///   "augmented": false, // Disables augmented but otherwise keeps defaults.
/// }
/// ```
class LspClientCodeLensConfiguration {
  final bool? _userOverride;
  final Map<String, Object?>? _codeLensSettings;

  LspClientCodeLensConfiguration(Object? userPreference)
    : _userOverride = userPreference is bool ? userPreference : null,
      _codeLensSettings =
          userPreference is Map<String, Object?> ? userPreference : null;

  /// Whether the "Go to Augmentation" CodeLens is enabled.
  bool get augmentation => _getUserPreference('augmentation', true);

  /// Whether the "Go to Augmented" CodeLens is enabled.
  bool get augmented => _getUserPreference('augmented', true);

  bool _getUserPreference(String name, bool defaultValue) {
    if (_userOverride != null) {
      return _userOverride;
    }
    return defaultValue
        // Default true, enable if not explicit false.
        ? (_codeLensSettings?[name] != false)
        // Default false, enable only if explicit true.
        : (_codeLensSettings?[name] == true);
  }
}

/// Provides access to both global and resource-specific client configuration.
///
/// Resource-specific config is currently only supported at the WorkspaceFolder
/// level so when looking up config for a resource, the nearest WorkspaceFolders
/// config will be used.
///
/// Settings prefixed with 'preview' are things that may not be completed but
/// may be exposed to users as something they can try out.
///
/// Settings prefixed with 'experimental' are things that may be incomplete or
/// still in development and users are not encouraged to try (but may be useful
/// for Dart developers to enable for development/testing).
class LspClientConfiguration {
  final path.Context pathContext;

  /// Global settings for the workspace.
  ///
  /// Used as a fallback for resource settings if no specific config is found
  /// for the resource.
  LspGlobalClientConfiguration _globalSettings = LspGlobalClientConfiguration(
    {},
  );

  /// Settings for each resource.
  ///
  /// Keys are string paths without trailing path separators (eg. 'C:\foo').
  final Map<String, LspResourceClientConfiguration> _resourceSettings =
      <String, LspResourceClientConfiguration>{};

  /// Pattern for stripping trailing slashes that may be been provided by the
  /// client (in WorkspaceFolder URIs) for consistent comparisons.
  final _trailingSlashPattern = RegExp(r'[\/]+$');

  LspClientConfiguration(this.pathContext);

  /// Returns the global configuration for the whole workspace.
  LspGlobalClientConfiguration get global => _globalSettings;

  /// Returns whether or not the provided new configuration changes any values
  /// that would affect analysis results.
  bool affectsAnalysisResults(LspGlobalClientConfiguration otherConfig) {
    // Check whether `TODO` settings have changed.
    var oldFlag = _globalSettings.showAllTodos;
    var newFlag = otherConfig.showAllTodos;
    var oldTypes = _globalSettings.showTodoTypes;
    var newTypes = otherConfig.showTodoTypes;
    return newFlag != oldFlag ||
        !const SetEquality().equals(oldTypes, newTypes);
  }

  /// Returns whether or not the provided new configuration changes any values
  /// that would require analysis roots to be updated.
  bool affectsAnalysisRoots(LspGlobalClientConfiguration otherConfig) {
    var oldExclusions = _globalSettings.analysisExcludedFolders;
    var newExclusions = otherConfig.analysisExcludedFolders;
    return !const ListEquality().equals(oldExclusions, newExclusions);
  }

  /// Returns config for a given resource.
  ///
  /// Because we only support config at the WorkspaceFolder level, this is done
  /// by finding the nearest WorkspaceFolder to [resourcePath] and using config
  /// for that.
  ///
  /// If no specific config is available, returns [global].
  LspResourceClientConfiguration forResource(String resourcePath) {
    var workspaceFolder = _getWorkspaceFolderPath(resourcePath);

    if (workspaceFolder == null) {
      return _globalSettings;
    }

    return _resourceSettings[_normaliseFolderPath(workspaceFolder)] ??
        _globalSettings;
  }

  /// Replaces all previously known configuration with updated values from the
  /// client.
  void replace(
    Map<String, Object?> globalConfig,
    Map<String, Map<String, Object?>> workspaceFolderConfig,
  ) {
    _globalSettings = LspGlobalClientConfiguration(globalConfig);

    _resourceSettings
      ..clear()
      ..addAll(
        workspaceFolderConfig.map(
          (key, value) => MapEntry(
            _normaliseFolderPath(key),
            LspResourceClientConfiguration(value, _globalSettings),
          ),
        ),
      );
  }

  /// Gets the path for the WorkspaceFolder closest to [resourcePath].
  String? _getWorkspaceFolderPath(String resourcePath) {
    var candidates =
        _resourceSettings.keys
            .where(
              (wfPath) =>
                  wfPath == _normaliseFolderPath(resourcePath) ||
                  pathContext.isWithin(wfPath, resourcePath),
            )
            .toList();
    candidates.sort((a, b) => -a.length.compareTo(b.length));
    return candidates.firstOrNull;
  }

  /// Normalises a folder path to never have a trailing path separator.
  String _normaliseFolderPath(String filePath) =>
      filePath.replaceAll(_trailingSlashPattern, '');
}

/// Wraps the client (editor) configuration to provide stronger typing and
/// handling of default values where a setting has not been supplied.
///
/// Settings in this class are only allowed to be configured at the workspace
/// level (they will be ignored at the resource level).
class LspGlobalClientConfiguration extends LspResourceClientConfiguration {
  late final codeLens = LspClientCodeLensConfiguration(_settings['codeLens']);

  LspGlobalClientConfiguration(Map<String, Object?> settings)
    : super(settings, null);

  List<String> get analysisExcludedFolders {
    // This setting is documented as a string array, but because editors are
    // unlikely to provide validation, support single strings for convenience.
    var value = _settings['analysisExcludedFolders'];
    if (value is String) {
      return [value];
    } else if (value is List && value.every((s) => s is String)) {
      return value.cast<String>();
    } else {
      return const [];
    }
  }

  /// Whether methods/functions in completion should include parens and argument
  /// placeholders when used in an invocation context.
  bool get completeFunctionCalls =>
      _settings['completeFunctionCalls'] as bool? ?? false;

  /// A flag for enabling interactive refactors flagged as experimental.
  ///
  /// This flag is likely to be used by both analysis server developers (working
  /// on new refactors) and users that want to test/provide feedback for
  /// incomplete refactors.
  bool get experimentalRefactors =>
      _settings['experimentalRefactors'] as bool? ?? false;

  /// Whether or not to include dependencies in `textDocument/workspaceSymbols`.
  ///
  /// If set to `false`, only analyzed files will be searched.
  /// Defaults to `true`.
  bool get includeDependenciesInWorkspaceSymbols =>
      _settings['includeDependenciesInWorkspaceSymbols'] as bool? ?? true;

  /// The users preferred kind of documentation for Hovers, Code Completion and
  /// other related panels in the UI.
  ///
  /// If the user has not expressed a preference, defaults to
  /// [DocumentationPreference.full].
  DocumentationPreference get preferredDocumentation {
    var value = _settings['documentation'];
    return switch (value) {
      'none' => DocumentationPreference.none,
      'summary' => DocumentationPreference.summary,
      _ => DocumentationPreference.full,
    };
  }

  /// A preview flag for enabling commit characters for completions.
  ///
  /// This is a temporary setting to allow this feature to be tested without
  /// defaulting to on for everybody.
  bool get previewCommitCharacters =>
      _settings['previewCommitCharacters'] as bool? ?? false;

  // Whether diagnostics should be generated for all `TODO` comments.
  bool get showAllTodos =>
      _settings['showTodos'] is bool ? _settings['showTodos'] as bool : false;

  // A specific set of `TODO` comments that should generate diagnostics.
  ///
  /// Codes are all forced UPPERCASE regardless of what the client supplies.
  ///
  /// [showAllTodos] should be checked first, as this will return an empty
  /// set if `showTodos` is a boolean.
  Set<String> get showTodoTypes =>
      _settings['showTodos'] is List
          ? (_settings['showTodos'] as List)
              .cast<String>()
              .map((kind) => kind.toUpperCase())
              .toSet()
          : const {};
}

/// Wraps the client (editor) configuration for a specific resource.
///
/// Settings in this class are only allowed to be configured either for a
/// resource or for the whole workspace.
///
/// Right now, we treat "resource" to always mean a WorkspaceFolder since no
/// known editors allow per-file configuration and it allows us to keep the
/// settings cached, invalidated only when WorkspaceFolders change.
class LspResourceClientConfiguration {
  /// The maximum number of completions to return for completion requests by
  /// default.
  ///
  /// This has been set fairly high initially to avoid changing behaviour too
  /// much. The Dart-Code extension will override this default with its own
  /// to gather feedback and then this can be adjusted accordingly.
  static const defaultMaxCompletions = 2000;

  final Map<String, Object?> _settings;
  final LspResourceClientConfiguration? _fallback;

  LspResourceClientConfiguration(this._settings, this._fallback);

  /// Whether to enable the SDK formatter.
  ///
  /// If this setting is `false`, the formatter will be unregistered with the
  /// client.
  bool get enableSdkFormatter =>
      _settings['enableSdkFormatter'] as bool? ??
      _fallback?.enableSdkFormatter ??
      true;

  /// Whether to include Snippets in code completion results.
  bool get enableSnippets {
    // Versions of Dart-Code earlier than v3.36 (1 Mar 2022) send
    // enableServerSnippets=false to opt-out of snippets. Later versions map
    // this version to the documented 'enableSnippets' setting in middleware.
    // Once the number of users on < 3.36 is insignificant, this check can be
    // removed. At 24 Mar 2022, approx 9% of users are on < 3.36.
    if (_settings['enableServerSnippets'] == false /* explicit false */ ) {
      return false;
    }

    return _settings['enableSnippets'] as bool? ??
        _fallback?.enableSnippets ??
        true;
  }

  /// The line length used when formatting documents if not specified in
  /// `analysis_options.yaml`.
  ///
  /// If null, the formatters default will be used.
  int? get lineLength =>
      _settings['lineLength'] as int? ?? _fallback?.lineLength;

  /// Requested maximum number of CompletionItems per completion request.
  ///
  /// If more than this are available, ranked items in the list will be
  /// truncated and `isIncomplete` is set to `true`.
  ///
  /// Unranked items are never truncated so it's still possible that more than
  /// this number of items will be returned.
  int get maxCompletionItems =>
      _settings['maxCompletionItems'] as int? ??
      _fallback?.maxCompletionItems ??
      defaultMaxCompletions;

  /// Whether to rename files when renaming classes inside them where the file
  /// and class name match.
  ///
  /// Values are "always", "prompt", "never". Any other values should be treated
  /// like "never".
  String get renameFilesWithClasses =>
      _settings['renameFilesWithClasses'] as String? ??
      _fallback?.renameFilesWithClasses ??
      'never';

  /// Whether to update imports and other directives when files are renamed.
  ///
  /// This setting works by controlling whether the server registers for
  /// `willRenameFiles` requests from the client. Changing the value after
  /// initialization will register/unregister appropriately.
  bool get updateImportsOnRename =>
      _settings['updateImportsOnRename'] as bool? ??
      _fallback?.updateImportsOnRename ??
      true;
}
