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

import 'package:analysis_server/src/protocol_server.dart' as server
    hide AnalysisError;
import 'package:collection/collection.dart';

/// Builds an LSP snippet string using the supplied edit groups.
///
/// [editGroups] are provided as absolute positions, where the edit will be
/// made starting at [editOffset].
///
/// [selectionOffset] is also absolute and assumes [text] will be
/// inserted at [editOffset].
String buildSnippetStringForEditGroups(
  String text, {
  required String filePath,
  required List<server.LinkedEditGroup> editGroups,
  required int editOffset,
  int? selectionOffset,
}) =>
    _buildSnippetString(
      text,
      filePath: filePath,
      editGroups: editGroups,
      editGroupsOffset: editOffset,
      selectionOffset:
          selectionOffset != null ? selectionOffset - editOffset : null,
    );

/// Builds an LSP snippet string with supplied ranges as tab stops.
///
/// [tabStopOffsetLengthPairs] are relative to the supplied text.
String buildSnippetStringWithTabStops(
  String text,
  List<int>? tabStopOffsetLengthPairs,
) =>
    _buildSnippetString(
      text,
      filePath: null,
      tabStopOffsetLengthPairs: tabStopOffsetLengthPairs,
    );

/// Builds an LSP snippet string with supplied ranges as tab stops.
///
/// [tabStopOffsetLengthPairs] are relative to the supplied text.
///
/// [selectionOffset]/[selectionLength] form a tab stop that is always "number 0"
/// which is the final tab stop.
///
/// [editGroups] are provided as absolute positions, where [text] is known to
/// start at [editGroupsOffset] in the final document.
String _buildSnippetString(
  String text, {
  required String? filePath,
  List<int>? tabStopOffsetLengthPairs,
  int? selectionOffset,
  int? selectionLength,
  List<server.LinkedEditGroup>? editGroups,
  int editGroupsOffset = 0,
}) {
  tabStopOffsetLengthPairs ??= const [];
  editGroups ??= const [];
  assert(tabStopOffsetLengthPairs.length % 2 == 0);

  /// Helper to create a [SnippetPlaceholder] for each position in a linked
  /// edit group.
  Iterable<SnippetPlaceholder> convertEditGroup(
    int index,
    server.LinkedEditGroup editGroup,
  ) {
    final validPositions = editGroup.positions.where((p) => p.file == filePath);
    // Create a placeholder for each position in the group.
    return validPositions.map(
      (position) => SnippetPlaceholder(
        // Make the position relative to the supplied text.
        position.offset - editGroupsOffset,
        editGroup.length,
        suggestions: editGroup.suggestions
            .map((suggestion) => suggestion.value)
            .toList(),
        // Use the index as an ID to keep all related positions together (so
        // the remain "linked").
        linkedGroupId: index,
        // If there is no selection, no tabstops, and only a single edit group
        // allow it to be the final tabstop.
        isFinal: selectionOffset == null &&
            (tabStopOffsetLengthPairs?.isEmpty ?? false) &&
            editGroups?.length == 1,
      ),
    );
  }

  // Convert selection/tab stops/edit groups all into the same format
  // (`_SnippetPlaceholder`) so they can be handled in a single pass through
  // the text.
  final placeholders = [
    // Selection.
    if (selectionOffset != null)
      SnippetPlaceholder(selectionOffset, selectionLength ?? 0, isFinal: true),

    // Tab stops.
    for (var i = 0; i < tabStopOffsetLengthPairs.length - 1; i += 2)
      SnippetPlaceholder(
        tabStopOffsetLengthPairs[i],
        tabStopOffsetLengthPairs[i + 1],
        // If there's only a single tab stop (and no selection/editGroups), mark
        // it as the final stop so it exit "snippet mode" when tabbed to.
        isFinal: selectionOffset == null &&
            editGroups.isEmpty &&
            tabStopOffsetLengthPairs.length == 2,
      ),

    // Linked edit groups.
    ...editGroups.expandIndexed(convertEditGroup),
  ];

  // Remove any groups outside of the range (it's possible the edit groups apply
  // to a different edit in the collection).
  placeholders.removeWhere((placeholder) =>
      placeholder.offset < 0 ||
      placeholder.offset + placeholder.length > text.length);

  /// If there are no edit groups, then placeholders are all simple and
  /// guaranteed to be in the correct order.
  final isPreSorted = editGroups.isEmpty;
  final builder = SnippetBuilder()
    ..appendPlaceholders(text, placeholders, isPreSorted: isPreSorted);
  return builder.value;
}

/// A helper for building for snippets using LSP/TextMate syntax.
///
/// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax
///
///  - $1, $2, etc. are used for tab stops
///  - ${1:foo} inserts a placeholder of foo
///  - ${1|foo,bar|} inserts a placeholder of foo with a selection list
///      containing "foo" and "bar"
class SnippetBuilder {
  /// The constant `$0` used do indicate a final tab stop in the snippet syntax.
  static const finalTabStop = r'$0';

  /// Regex used by [escapeSnippetChoiceText].
  static final _escapeSnippetChoiceTextRegex =
      RegExp(r'[$}\\\|,]'); // Replace any of $ } \ | ,

  /// Regex used by [escapeSnippetPlainText].
  static final _escapeSnippetPlainTextRegex =
      RegExp(r'[$\\]'); // Replace any of $ \

  /// Regex used by [escapeSnippetVariableText].
  static final _escapeSnippetVariableTextRegex =
      RegExp(r'[$}\\]'); // Replace any of $ } \

  final _buffer = StringBuffer();

  var _nextPlaceholder = 1;

  /// The built snippet text using the LSP snippet syntax.
  String get value => _buffer.toString();

  /// Appends a placeholder with a set of choices to choose from.
  ///
  /// If there are 0 or 1 choices, a placeholder will be inserted instead.
  ///
  /// Returns the placeholder number used.
  int appendChoice(Set<String> uniqueChoices, {int? placeholderNumber}) {
    // If there's only 0/1 items, we can downgrade this to a placeholder.
    if (uniqueChoices.length <= 1) {
      return appendPlaceholder(
        uniqueChoices.firstOrNull ?? '',
        placeholderNumber: placeholderNumber,
      );
    }

    placeholderNumber = _usePlaceholerNumber(placeholderNumber);

    final escapedChoices = uniqueChoices.map(escapeSnippetChoiceText).join(',');
    _buffer.write('\${$placeholderNumber|$escapedChoices|}');

    return placeholderNumber;
  }

  /// Appends a placeholder with the given text.
  ///
  /// If the text is empty, inserts a tab stop instead.
  ///
  /// Returns the placeholder number used.
  int appendPlaceholder(String text, {int? placeholderNumber}) {
    // If there's no text, we can downgrade this to a tab stop.
    if (text.isEmpty) {
      return appendTabStop(placeholderNumber: placeholderNumber);
    }

    placeholderNumber = _usePlaceholerNumber(placeholderNumber);

    final escapedText = escapeSnippetVariableText(text);
    _buffer.write(r'${');
    _buffer.write(placeholderNumber);
    _buffer.write(':');
    _buffer.write(escapedText);
    _buffer.write('}');

    return placeholderNumber;
  }

  /// Appends a tab stop.
  ///
  /// Returns the placeholder number used.
  int appendTabStop({int? placeholderNumber}) {
    placeholderNumber = _usePlaceholerNumber(placeholderNumber);

    _buffer.write(r'$');
    _buffer.write(placeholderNumber);

    return placeholderNumber;
  }

  /// Appends normal text (escaping it as required).
  void appendText(String text) {
    _buffer.write(escapeSnippetPlainText(text));
  }

  /// Generates the current and next placeholder numbers.
  int _usePlaceholerNumber(int? placeholderNumber) {
    // If a number was not supplied, use thenext available one.
    placeholderNumber ??= _nextPlaceholder;
    // If the number we used was the highest seen, set the next one after it.
    _nextPlaceholder = math.max(_nextPlaceholder, placeholderNumber + 1);

    return placeholderNumber;
  }

  /// Escapes a string use inside a "choice" in a snippet.
  ///
  /// Similar to [escapeSnippetPlainText], but choices are delimited/separated
  /// by pipes and commas (`${1:|a,b,c|}`).
  static String escapeSnippetChoiceText(String input) => _escapeCharacters(
        input,
        _escapeSnippetChoiceTextRegex,
      );

  /// Escapes a string to be used in an LSP edit that uses Snippet mode where the
  /// text is outside of a snippet token.
  ///
  /// Snippets can contain special markup like `${a:b}` so `$` needs escaping
  /// as does `\` so it's not interpreted as an escape.
  static String escapeSnippetPlainText(String input) =>
      _escapeCharacters(input, _escapeSnippetPlainTextRegex);

  /// Escapes a string to be used inside a snippet token.
  ///
  /// Similar to [escapeSnippetPlainText] but additionally escapes `}` so that the
  /// token is not ended early if the included text contains braces.
  static String escapeSnippetVariableText(String input) => _escapeCharacters(
        input,
        _escapeSnippetVariableTextRegex,
      );

  /// Escapes [pattern] in [input] with backslashes.
  static String _escapeCharacters(String input, Pattern pattern) =>
      input.replaceAllMapped(pattern, (c) => '\\${c[0]}');
}

/// Information about an individual placeholder/tab stop in a piece of code.
///
/// Each placeholder represents a single position into the code, so a linked
/// edit group with 2 positions will be represented as two instances of this
/// class (with the same [linkedGroupId]).
class SnippetPlaceholder {
  final int offset;
  final int length;
  final List<String>? suggestions;
  final int? linkedGroupId;
  final bool isFinal;

  SnippetPlaceholder(
    this.offset,
    this.length, {
    this.suggestions,
    this.linkedGroupId,
    this.isFinal = false,
  });
}

/// Helpers for [SnippetBuilder] that do not relate to building the main snippet
/// syntax (for example, converting from intermediate structures).
///
/// `isPreSorted` is a performance optimisation that allows skipping some
/// sorting if it's guaranteed that placeholders are already in source-order.
extension SnippetBuilderExtensions on SnippetBuilder {
  void appendPlaceholders(
    String text,
    List<SnippetPlaceholder> placeholders, {
    required bool isPreSorted,
  }) {
    // Ensure placeholders are in the order they're visible in the source so
    // tabbing through them doesn't appear to jump around.
    if (!isPreSorted) {
      placeholders.sortBy<num>((placeholder) => placeholder.offset);
    }

    // We need to use the same placeholder number for all placeholders in the
    // same linked group, so the first time we see a linked item, store its
    // placeholder number here, so subsequent placeholders for the same linked
    // group can reuse it.
    final placeholderIdForLinkedGroupId = <int, int>{};

    var offset = 0;
    for (final placeholder in placeholders) {
      // Add any text that came before this placeholder to the result.
      appendText(text.substring(offset, placeholder.offset));

      final linkedGroupId = placeholder.linkedGroupId;
      int? thisPaceholderNumber;
      // Override the placeholder number if it's the final one (0) or needs to
      // re-use an existing one for a linked group.
      if (placeholder.isFinal) {
        thisPaceholderNumber = 0;
      } else if (linkedGroupId != null) {
        thisPaceholderNumber = placeholderIdForLinkedGroupId[linkedGroupId];
      }

      // Append the placeholder/choices.
      final placeholderText = text.substring(
        placeholder.offset,
        placeholder.offset + placeholder.length,
      );
      // appendChoice handles mapping empty/single suggestions to a normal
      // placeholder but it's faster if we can avoid putting a single item into
      // a set and then detecting it.
      if (placeholder.suggestions == null) {
        thisPaceholderNumber = appendPlaceholder(
          placeholderText,
          placeholderNumber: thisPaceholderNumber,
        );
      } else {
        final choices = <String>{
          if (placeholderText.isNotEmpty) placeholderText,
          ...?placeholder.suggestions,
        };
        thisPaceholderNumber = appendChoice(
          choices,
          placeholderNumber: thisPaceholderNumber,
        );
      }

      // Track where we're up to.
      offset = placeholder.offset + placeholder.length;

      // Store the placeholder number used for linked groups so it can be reused
      // by subsequent references to it.
      if (linkedGroupId != null) {
        placeholderIdForLinkedGroupId[linkedGroupId] = thisPaceholderNumber;
      }
    }

    // Add any remaining text that was after the last placeholder.
    appendText(text.substring(offset));
  }
}
