// Copyright (c) 2013, 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.

/// Tools to help implement refactoring like transformations to Dart code.
///
/// [TextEditTransaction] supports making a series of changes to a text buffer.
/// [guessIndent] helps to guess the appropriate indentiation for the new code.
library;

import 'package:source_span/source_span.dart';

import 'printer.dart';
import 'src/utils.dart';

/// Editable text transaction.
///
/// Applies a series of edits using original location
/// information, and composes them into the edited string.
class TextEditTransaction {
  final SourceFile? file;
  final String original;
  final _edits = <_TextEdit>[];

  /// Creates a new transaction.
  TextEditTransaction(this.original, this.file);

  bool get hasEdits => _edits.isNotEmpty;

  /// Edit the original text, replacing text on the range [begin] and [end]
  /// with the [replacement]. [replacement] can be either a string or a
  /// [NestedPrinter].
  void edit(int begin, int end, Object replacement) {
    _edits.add(_TextEdit(begin, end, replacement));
  }

  /// Create a source map [SourceLocation] for [offset], if [file] is not
  /// `null`.
  SourceLocation? _loc(int offset) => file?.location(offset);

  /// Applies all pending [edit]s and returns a [NestedPrinter] containing the
  /// rewritten string and source map information. [file]`.location` is given to
  /// the underlying printer to indicate the name of the generated file that
  /// will contains the source map information.
  ///
  /// Throws [UnsupportedError] if the edits were overlapping. If no edits were
  /// made, the printer simply contains the original string.
  NestedPrinter commit() {
    var printer = NestedPrinter();
    if (_edits.isEmpty) {
      return printer..add(original, location: _loc(0), isOriginal: true);
    }

    // Sort edits by start location.
    _edits.sort();

    var consumed = 0;
    for (var edit in _edits) {
      if (consumed > edit.begin) {
        var sb = StringBuffer();
        sb
          ..write(file?.location(edit.begin).toolString)
          ..write(': overlapping edits. Insert at offset ')
          ..write(edit.begin)
          ..write(' but have consumed ')
          ..write(consumed)
          ..write(' input characters. List of edits:');
        for (var e in _edits) {
          sb
            ..write('\n    ')
            ..write(e);
        }
        throw UnsupportedError(sb.toString());
      }

      // Add characters from the original string between this edit and the last
      // one, if any.
      var betweenEdits = original.substring(consumed, edit.begin);
      printer
        ..add(betweenEdits, location: _loc(consumed), isOriginal: true)
        ..add(edit.replace, location: _loc(edit.begin));
      consumed = edit.end;
    }

    // Add any text from the end of the original string that was not replaced.
    printer.add(original.substring(consumed),
        location: _loc(consumed), isOriginal: true);
    return printer;
  }
}

class _TextEdit implements Comparable<_TextEdit> {
  final int begin;
  final int end;

  /// The replacement used by the edit, can be a string or a [NestedPrinter].
  final Object replace;

  _TextEdit(this.begin, this.end, this.replace);

  int get length => end - begin;

  @override
  String toString() => '(Edit @ $begin,$end: "$replace")';

  @override
  int compareTo(_TextEdit other) {
    var diff = begin - other.begin;
    if (diff != 0) return diff;
    return end - other.end;
  }
}

/// Returns all whitespace characters at the start of [charOffset]'s line.
String guessIndent(String code, int charOffset) {
  // Find the beginning of the line
  var lineStart = 0;
  for (var i = charOffset - 1; i >= 0; i--) {
    var c = code.codeUnitAt(i);
    if (c == lineFeed || c == carriageReturn) {
      lineStart = i + 1;
      break;
    }
  }

  // Grab all the whitespace
  var whitespaceEnd = code.length;
  for (var i = lineStart; i < code.length; i++) {
    var c = code.codeUnitAt(i);
    if (c != _space && c != _tab) {
      whitespaceEnd = i;
      break;
    }
  }

  return code.substring(lineStart, whitespaceEnd);
}

const int _tab = 9;
const int _space = 32;
