// 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:meta/meta.dart';
import 'package:yaml/yaml.dart';

import 'equality.dart';
import 'errors.dart';
import 'list_mutations.dart';
import 'map_mutations.dart';
import 'source_edit.dart';
import 'strings.dart';
import 'utils.dart';
import 'wrap.dart';

/// An interface for modifying [YAML][1] documents while preserving comments
/// and whitespaces.
///
/// YAML parsing is supported by `package:yaml`, and modifications are performed
/// as string operations. An error will be thrown if internal assertions fail -
/// such a situation should be extremely rare, and should only occur with
/// degenerate formatting.
///
/// Most modification methods require the user to pass in an `Iterable<Object>`
/// path that holds the keys/indices to navigate to the element.
///
/// **Example:**
/// ```yaml
/// a: 1
/// b: 2
/// c:
///   - 3
///   - 4
///   - {e: 5, f: [6, 7]}
/// ```
///
/// To get to `7`, our path will be `['c', 2, 'f', 1]`. The path for the base
/// object is the empty array `[]`. All modification methods will throw a
/// [ArgumentError] if the path provided is invalid. Note also that that the
/// order of elements in the path is important, and it should be arranged in
/// order of calling, with the first element being the first key or index to be
/// called.
///
/// In most modification methods, users are required to pass in a value to be
/// used for updating the YAML tree. This value is only allowed to either be a
/// valid scalar that is recognizable by YAML (i.e. `bool`, `String`, `List`,
/// `Map`, `num`, `null`) or a [YamlNode]. Should the user want to specify
/// the style to be applied to the value passed in, the user may wrap the value
/// using [wrapAsYamlNode] while passing in the appropriate `scalarStyle` or
/// `collectionStyle`. While we try to respect the style that is passed in,
/// there will be instances where the formatting will not result in valid YAML,
/// and as such we will fallback to a default formatting while preserving the
/// content.
///
/// To dump the YAML after all the modifications have been completed, simply
/// call [toString()].
///
/// [1]: https://yaml.org/
@sealed
class YamlEditor {
  final List<SourceEdit> _edits = [];

  /// List of [SourceEdit]s that have been applied to [_yaml] since the creation
  /// of this instance, in chronological order. Intended to be compatible with
  /// `package:analysis_server`.
  ///
  /// The [SourceEdit] objects can be serialized to JSON using the `toJSON`
  /// function, deserialized using [SourceEdit.fromJson], and applied to a
  /// string using the `apply` function. Multiple [SourceEdit]s can be applied
  /// to a string using [SourceEdit.applyAll].
  ///
  /// For more information, refer to the [SourceEdit] class.
  List<SourceEdit> get edits => [..._edits];

  /// Current YAML string.
  String _yaml;

  /// Root node of YAML AST.
  YamlNode _contents;

  /// Stores the list of nodes in [_contents] that are connected by aliases.
  ///
  /// When a node is anchored with an alias and subsequently referenced,
  /// the full content of the anchored node is thought to be copied in the
  /// following references.
  ///
  /// **Example:**
  /// ```dart
  /// a: &SS Sammy Sosa
  /// b: *SS
  /// ```
  ///
  /// is equivalent to
  ///
  /// ```dart
  /// a: Sammy Sosa
  /// b: Sammy Sosa
  /// ```
  ///
  /// As such, aliased nodes have to be treated with special caution when
  /// any modification is taking place.
  ///
  /// See 7.1 Alias Nodes: https://yaml.org/spec/1.2/spec.html#id2786196
  Set<YamlNode> _aliases = {};

  /// Returns the current YAML string.
  @override
  String toString() => _yaml;

  factory YamlEditor(String yaml) => YamlEditor._(yaml);

  YamlEditor._(this._yaml) : _contents = loadYamlNode(_yaml) {
    _initialize();
  }

  /// Traverses the YAML tree formed to detect alias nodes.
  void _initialize() {
    _aliases = {};

    /// Performs a DFS on [_contents] to detect alias nodes.
    final visited = <YamlNode>{};
    void collectAliases(YamlNode node) {
      if (visited.add(node)) {
        if (node is YamlMap) {
          node.nodes.forEach((key, value) {
            collectAliases(key as YamlNode);
            collectAliases(value);
          });
        } else if (node is YamlList) {
          node.nodes.forEach(collectAliases);
        }
      } else {
        _aliases.add(node);
      }
    }

    collectAliases(_contents);
  }

  /// Parses the document to return [YamlNode] currently present at [path].
  ///
  /// If no [YamlNode]s exist at [path], the result of invoking the [orElse]
  /// function is returned.
  ///
  /// If [orElse] is omitted, it defaults to throwing a [ArgumentError].
  ///
  /// To get a default value when [path] does not point to a value in the
  /// [YamlNode]-tree, simply pass `orElse: () => ...`.
  ///
  /// **Example:** (using orElse)
  /// ```dart
  /// final myYamlEditor('{"key": "value"}');
  /// final node = myYamlEditor.valueAt(
  ///   ['invalid', 'path'],
  ///   orElse: () => wrapAsYamlNode(null),
  /// );
  /// print(node.value); // null
  /// ```
  ///
  /// **Example:** (common usage)
  /// ```dart
  ///   final doc = YamlEditor('''
  /// a: 1
  /// b:
  ///   d: 4
  ///   e: [5, 6, 7]
  /// c: 3
  /// ''');
  /// print(doc.parseAt(['b', 'e', 2])); // 7
  /// ```
  /// The value returned by [parseAt] is invalidated when the documented is
  /// mutated, as illustrated below:
  ///
  /// **Example:** (old [parseAt] value is invalidated)
  /// ```dart
  /// final doc = YamlEditor("YAML: YAML Ain't Markup Language");
  /// final node = doc.parseAt(['YAML']);
  ///
  /// print(node.value); // Expected output: "YAML Ain't Markup Language"
  ///
  /// doc.update(['YAML'], 'YAML');
  ///
  /// final newNode = doc.parseAt(['YAML']);
  ///
  /// // Note that the value does not change
  /// print(newNode.value); // "YAML"
  /// print(node.value); // "YAML Ain't Markup Language"
  /// ```
  YamlNode parseAt(Iterable<Object?> path, {YamlNode Function()? orElse}) {
    return _traverse(path, orElse: orElse);
  }

  /// Sets [value] in the [path].
  ///
  /// There is a subtle difference between [update] and [remove] followed by
  /// an [insertIntoList], because [update] preserves comments at the same
  /// level.
  ///
  /// Throws a [ArgumentError] if [path] is invalid.
  ///
  /// Throws an [AliasException] if a node on [path] is an alias or anchor.
  ///
  /// **Example:** (using [update])
  /// ```dart
  /// final doc = YamlEditor('''
  ///   - 0
  ///   - 1 # comment
  ///   - 2
  /// ''');
  /// doc.update([1], 'test');
  /// ```
  ///
  /// **Expected Output:**
  /// ```yaml
  ///   - 0
  ///   - test # comment
  ///   - 2
  /// ```
  ///
  /// **Example:** (using [remove] and [insertIntoList])
  /// ```dart
  /// final doc2 = YamlEditor('''
  ///   - 0
  ///   - 1 # comment
  ///   - 2
  /// ''');
  /// doc2.remove([1]);
  /// doc2.insertIntoList([], 1, 'test');
  /// ```
  ///
  /// **Expected Output:**
  /// ```yaml
  ///   - 0
  ///   - test
  ///   - 2
  /// ```
  void update(Iterable<Object?> path, Object? value) {
    final valueNode = wrapAsYamlNode(value);

    if (path.isEmpty) {
      final start = _contents.span.start.offset;
      final end = getContentSensitiveEnd(_contents);
      final lineEnding = getLineEnding(_yaml);
      final edit = SourceEdit(
          start, end - start, yamlEncodeBlockString(valueNode, 0, lineEnding));

      return _performEdit(edit, path, valueNode);
    }

    final pathAsList = path.toList();
    final collectionPath = pathAsList.take(path.length - 1);
    final keyOrIndex = pathAsList.last;
    final parentNode = _traverse(collectionPath, checkAlias: true);

    if (parentNode is YamlList) {
      if (keyOrIndex is! int) {
        throw PathError(path, path, parentNode);
      }
      final expected = wrapAsYamlNode(
        [...parentNode.nodes]..[keyOrIndex] = valueNode,
      );

      return _performEdit(updateInList(this, parentNode, keyOrIndex, valueNode),
          collectionPath, expected);
    }

    if (parentNode is YamlMap) {
      final expectedMap =
          updatedYamlMap(parentNode, (nodes) => nodes[keyOrIndex] = valueNode);
      return _performEdit(updateInMap(this, parentNode, keyOrIndex, valueNode),
          collectionPath, expectedMap);
    }

    throw PathError.unexpected(
        path, 'Scalar $parentNode does not have key $keyOrIndex');
  }

  /// Appends [value] to the list at [path].
  ///
  /// Throws a [ArgumentError] if the element at the given path is not a
  /// [YamlList] or if the path is invalid.
  ///
  /// Throws an [AliasException] if a node on [path] is an alias or anchor.
  ///
  /// **Example:**
  /// ```dart
  /// final doc = YamlEditor('[0, 1]');
  /// doc.appendToList([], 2); // [0, 1, 2]
  /// ```
  void appendToList(Iterable<Object?> path, Object? value) {
    final yamlList = _traverseToList(path);

    insertIntoList(path, yamlList.length, value);
  }

  /// Prepends [value] to the list at [path].
  ///
  /// Throws a [ArgumentError] if the element at the given path is not a
  /// [YamlList] or if the path is invalid.
  ///
  /// Throws an [AliasException] if a node on [path] is an alias or anchor.
  ///
  /// **Example:**
  /// ```dart
  /// final doc = YamlEditor('[1, 2]');
  /// doc.prependToList([], 0); // [0, 1, 2]
  /// ```
  void prependToList(Iterable<Object?> path, Object? value) {
    insertIntoList(path, 0, value);
  }

  /// Inserts [value] into the list at [path].
  ///
  /// [index] must be non-negative and no greater than the list's length.
  ///
  /// Throws a [ArgumentError] if the element at the given path is not a
  /// [YamlList] or if the path is invalid.
  ///
  /// Throws an [AliasException] if a node on [path] is an alias or anchor.
  ///
  /// **Example:**
  /// ```dart
  /// final doc = YamlEditor('[0, 2]');
  /// doc.insertIntoList([], 1, 1); // [0, 1, 2]
  /// ```
  void insertIntoList(Iterable<Object?> path, int index, Object? value) {
    final valueNode = wrapAsYamlNode(value);

    final list = _traverseToList(path, checkAlias: true);
    RangeError.checkValueInInterval(index, 0, list.length);

    final edit = insertInList(this, list, index, valueNode);
    final expected = wrapAsYamlNode(
      [...list.nodes]..insert(index, valueNode),
    );

    _performEdit(edit, path, expected);
  }

  /// Changes the contents of the list at [path] by removing [deleteCount]
  /// items at [index], and inserting [values] in-place. Returns the elements
  /// that are deleted.
  ///
  /// [index] and [deleteCount] must be non-negative and [index] + [deleteCount]
  /// must be no greater than the list's length.
  ///
  /// Throws a [ArgumentError] if the element at the given path is not a
  /// [YamlList] or if the path is invalid.
  ///
  /// Throws an [AliasException] if a node on [path] is an alias or anchor.
  ///
  /// **Example:**
  /// ```dart
  /// final doc = YamlEditor('[Jan, March, April, June]');
  /// doc.spliceList([], 1, 0, ['Feb']); // [Jan, Feb, March, April, June]
  /// doc.spliceList([], 4, 1, ['May']); // [Jan, Feb, March, April, May]
  /// ```
  Iterable<YamlNode> spliceList(Iterable<Object?> path, int index,
      int deleteCount, Iterable<Object?> values) {
    final list = _traverseToList(path, checkAlias: true);

    RangeError.checkValueInInterval(index, 0, list.length);
    RangeError.checkValueInInterval(index + deleteCount, 0, list.length);

    final nodesToRemove = list.nodes.getRange(index, index + deleteCount);

    // Perform addition of elements before removal to avoid scenarios where
    // a block list gets emptied out to {} to avoid changing collection styles
    // where possible.

    // Reverse [values] and insert them.
    final reversedValues = values.toList().reversed;
    for (final value in reversedValues) {
      insertIntoList(path, index, value);
    }

    for (var i = 0; i < deleteCount; i++) {
      remove([...path, index + values.length]);
    }

    return nodesToRemove;
  }

  /// Removes the node at [path]. Comments "belonging" to the node will be
  /// removed while surrounding comments will be left untouched.
  ///
  /// Throws an [ArgumentError] if [path] is invalid.
  ///
  /// Throws an [AliasException] if a node on [path] is an alias or anchor.
  ///
  /// **Example:**
  /// ```dart
  /// final doc = YamlEditor('''
  /// - 0 # comment 0
  /// # comment A
  /// - 1 # comment 1
  /// # comment B
  /// - 2 # comment 2
  /// ''');
  /// doc.remove([1]);
  /// ```
  ///
  /// **Expected Result:**
  /// ```dart
  /// '''
  /// - 0 # comment 0
  /// # comment A
  /// # comment B
  /// - 2 # comment 2
  /// '''
  /// ```
  YamlNode remove(Iterable<Object?> path) {
    late SourceEdit edit;
    late YamlNode expectedNode;
    final nodeToRemove = _traverse(path, checkAlias: true);

    if (path.isEmpty) {
      edit = SourceEdit(0, _yaml.length, '');
      expectedNode = wrapAsYamlNode(null);

      /// Parsing an empty YAML document returns YamlScalar with value `null`.
      _performEdit(edit, path, expectedNode);
      return nodeToRemove;
    }

    final pathAsList = path.toList();
    final collectionPath = pathAsList.take(path.length - 1);
    final keyOrIndex = pathAsList.last;
    final parentNode = _traverse(collectionPath);

    if (parentNode is YamlList) {
      edit = removeInList(this, parentNode, keyOrIndex as int);
      expectedNode = wrapAsYamlNode(
        [...parentNode.nodes]..removeAt(keyOrIndex),
      );
    } else if (parentNode is YamlMap) {
      edit = removeInMap(this, parentNode, keyOrIndex);

      expectedNode =
          updatedYamlMap(parentNode, (nodes) => nodes.remove(keyOrIndex));
    }

    _performEdit(edit, collectionPath, expectedNode);

    return nodeToRemove;
  }

  /// Traverses down [path] to return the [YamlNode] at [path] if successful.
  ///
  /// If no [YamlNode]s exist at [path], the result of invoking the [orElse]
  /// function is returned.
  ///
  /// If [orElse] is omitted, it defaults to throwing a [PathError].
  ///
  /// If [checkAlias] is `true`, throw [AliasException] if an aliased node is
  /// encountered.
  YamlNode _traverse(Iterable<Object?> path,
      {bool checkAlias = false, YamlNode Function()? orElse}) {
    if (path.isEmpty) return _contents;

    var currentNode = _contents;
    final pathList = path.toList();

    for (var i = 0; i < pathList.length; i++) {
      final keyOrIndex = pathList[i];

      if (checkAlias && _aliases.contains(currentNode)) {
        throw AliasException(path, currentNode);
      }

      if (currentNode is YamlList) {
        final list = currentNode;
        if (!isValidIndex(keyOrIndex, list.length)) {
          return _pathErrorOrElse(path, path.take(i + 1), list, orElse);
        }

        currentNode = list.nodes[keyOrIndex as int];
      } else if (currentNode is YamlMap) {
        final map = currentNode;

        if (!containsKey(map, keyOrIndex)) {
          return _pathErrorOrElse(path, path.take(i + 1), map, orElse);
        }
        final keyNode = getKeyNode(map, keyOrIndex);

        if (checkAlias) {
          if (_aliases.contains(keyNode)) throw AliasException(path, keyNode);
        }

        currentNode = map.nodes[keyNode]!;
      } else {
        return _pathErrorOrElse(path, path.take(i + 1), currentNode, orElse);
      }
    }

    if (checkAlias) _assertNoChildAlias(path, currentNode);

    return currentNode;
  }

  /// Throws a [PathError] if [orElse] is not provided, returns the result
  /// of invoking the [orElse] function otherwise.
  YamlNode _pathErrorOrElse(Iterable<Object?> path, Iterable<Object?> subPath,
      YamlNode parent, YamlNode Function()? orElse) {
    if (orElse == null) throw PathError(path, subPath, parent);
    return orElse();
  }

  /// Asserts that [node] and none its children are aliases
  void _assertNoChildAlias(Iterable<Object?> path, [YamlNode? node]) {
    if (node == null) return _assertNoChildAlias(path, _traverse(path));
    if (_aliases.contains(node)) throw AliasException(path, node);

    if (node is YamlScalar) return;

    if (node is YamlList) {
      for (var i = 0; i < node.length; i++) {
        final updatedPath = [...path, i];
        _assertNoChildAlias(updatedPath, node.nodes[i]);
      }
    }

    if (node is YamlMap) {
      final keyList = node.keys.toList();
      for (var i = 0; i < node.length; i++) {
        final updatedPath = [...path, keyList[i]];
        if (_aliases.contains(keyList[i])) {
          throw AliasException(path, keyList[i] as YamlNode);
        }
        _assertNoChildAlias(updatedPath, node.nodes[keyList[i]]);
      }
    }
  }

  /// Traverses down the provided [path] to return the [YamlList] at [path].
  ///
  /// Convenience function to ensure that a [YamlList] is returned.
  ///
  /// Throws [ArgumentError] if the element at the given path is not a
  /// [YamlList] or if the path is invalid. If [checkAlias] is `true`, and an
  /// aliased node is encountered along [path], an [AliasException] will be
  /// thrown.
  YamlList _traverseToList(Iterable<Object?> path, {bool checkAlias = false}) {
    final possibleList = _traverse(path, checkAlias: checkAlias);

    if (possibleList is YamlList) {
      return possibleList;
    } else {
      throw PathError.unexpected(
          path, 'Path $path does not point to a YamlList!');
    }
  }

  /// Utility method to replace the substring of [_yaml] according to [edit].
  ///
  /// When [_yaml] is modified with this method, the resulting string is parsed
  /// and reloaded and traversed down [path] to ensure that the reloaded YAML
  /// tree is equal to our expectations by deep equality of values. Throws an
  /// [AssertionError] if the two trees do not match.
  void _performEdit(
      SourceEdit edit, Iterable<Object?> path, YamlNode expectedNode) {
    final expectedTree = _deepModify(_contents, path, [], expectedNode);
    final initialYaml = _yaml;
    _yaml = edit.apply(_yaml);

    try {
      _initialize();
    } on YamlException {
      throw createAssertionError(
          'Failed to produce valid YAML after modification.',
          initialYaml,
          _yaml);
    }

    final actualTree = loadYamlNode(_yaml);
    if (!deepEquals(actualTree, expectedTree)) {
      throw createAssertionError(
          'Modification did not result in expected result.',
          initialYaml,
          _yaml);
    }

    _contents = actualTree;
    _edits.add(edit);
  }

  /// Utility method to produce an updated YAML tree equivalent to converting
  /// the [YamlNode] at [path] to be [expectedNode]. [subPath] holds the portion
  /// of [path] that has been traversed thus far.
  ///
  /// Throws a [PathError] if path is invalid.
  ///
  /// When called, it creates a new [YamlNode] of the same type as [tree], and
  /// copies its children over, except for the child that is on the path. Doing
  /// so allows us to "update" the immutable [YamlNode] without having to clone
  /// the whole tree.
  ///
  /// [SourceSpan]s in this new tree are not guaranteed to be accurate.
  YamlNode _deepModify(YamlNode tree, Iterable<Object?> path,
      Iterable<Object?> subPath, YamlNode expectedNode) {
    RangeError.checkValueInInterval(subPath.length, 0, path.length);

    if (path.length == subPath.length) return expectedNode;

    final keyOrIndex = path.elementAt(subPath.length);

    if (tree is YamlList) {
      if (!isValidIndex(keyOrIndex, tree.length)) {
        throw PathError(path, subPath, tree);
      }

      return wrapAsYamlNode([...tree.nodes]..[keyOrIndex as int] = _deepModify(
          tree.nodes[keyOrIndex],
          path,
          path.take(subPath.length + 1),
          expectedNode));
    }

    if (tree is YamlMap) {
      return updatedYamlMap(
          tree,
          (nodes) => nodes[keyOrIndex] = _deepModify(
              nodes[keyOrIndex] as YamlNode,
              path,
              path.take(subPath.length + 1),
              expectedNode));
    }

    /// Should not ever reach here.
    throw PathError(path, subPath, tree);
  }
}
