// Copyright (c) 2017, 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 'dart:collection';
import 'dart:math' as math;

import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';

/**
 * A builder used to build a [SourceChange].
 */
class ChangeBuilderImpl implements ChangeBuilder {
  /**
   * The end-of-line marker used in the file being edited, or `null` if the
   * default marker should be used.
   */
  String eol = null;

  /**
   * The change that is being built.
   */
  final SourceChange _change = new SourceChange('');

  /**
   * A table mapping group ids to the associated linked edit groups.
   */
  final Map<String, LinkedEditGroup> _linkedEditGroups =
      <String, LinkedEditGroup>{};

  /**
   * The range of the selection for the change being built, or `null` if there
   * is no selection.
   */
  SourceRange _selectionRange;

  /**
   * The set of [Position]s that belong to the current [EditBuilderImpl] and
   * should not be updated in result of inserting this builder.
   */
  final Set<Position> _lockedPositions = new HashSet<Position>.identity();

  /**
   * Initialize a newly created change builder.
   */
  ChangeBuilderImpl();

  @override
  SourceRange get selectionRange => _selectionRange;

  @override
  SourceChange get sourceChange {
    _linkedEditGroups.forEach((String name, LinkedEditGroup group) {
      _change.addLinkedEditGroup(group);
    });
    _linkedEditGroups.clear();
    return _change;
  }

  @override
  Future<void> addFileEdit(
      String path, void buildFileEdit(FileEditBuilder builder)) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    FileEditBuilderImpl builder = await createFileEditBuilder(path);
    if (builder == null) {
      return;
    }

    buildFileEdit(builder);
    if (builder.hasEdits) {
      _change.addFileEdit(builder.fileEdit);
      await builder.finalize();
    }
  }

  /**
   * Create and return a [FileEditBuilder] that can be used to build edits to
   * the file with the given [path] and [timeStamp].
   */
  Future<FileEditBuilderImpl> createFileEditBuilder(String path) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return new FileEditBuilderImpl(this, path, 0);
  }

  /**
   * Return the linked edit group with the given [groupName], creating it if it
   * did not already exist.
   */
  LinkedEditGroup getLinkedEditGroup(String groupName) {
    LinkedEditGroup group = _linkedEditGroups[groupName];
    if (group == null) {
      group = new LinkedEditGroup.empty();
      _linkedEditGroups[groupName] = group;
    }
    return group;
  }

  @override
  void setSelection(Position position) {
    _change.selection = position;
  }

  void _setSelectionRange(SourceRange range) {
    _selectionRange = range;
  }

  /**
   * Update the offsets of any positions that occur at or after the given
   * [offset] such that the positions are offset by the given [delta]. Positions
   * occur in linked edit groups and as the post-change selection.
   */
  void _updatePositions(int offset, int delta) {
    void _updatePosition(Position position) {
      if (position.offset >= offset && !_lockedPositions.contains(position)) {
        position.offset = position.offset + delta;
      }
    }

    for (LinkedEditGroup group in _linkedEditGroups.values) {
      for (Position position in group.positions) {
        _updatePosition(position);
      }
    }
    Position selection = _change.selection;
    if (selection != null) {
      _updatePosition(selection);
    }
  }
}

/**
 * A builder used to build a [SourceEdit] as part of a [SourceFileEdit].
 */
class EditBuilderImpl implements EditBuilder {
  /**
   * The builder being used to create the source file edit of which the source
   * edit will be a part.
   */
  final FileEditBuilderImpl fileEditBuilder;

  /**
   * The offset of the region being replaced.
   */
  final int offset;

  /**
   * The length of the region being replaced.
   */
  final int length;

  /**
   * The range of the selection for the change being built, or `null` if the
   * selection is not inside the change being built.
   */
  SourceRange _selectionRange;

  /**
   * The end-of-line marker used in the file being edited, or `null` if the
   * default marker should be used.
   */
  String _eol = null;

  /**
   * The buffer in which the content of the edit is being composed.
   */
  final StringBuffer _buffer = new StringBuffer();

  /**
   * Initialize a newly created builder to build a source edit.
   */
  EditBuilderImpl(this.fileEditBuilder, this.offset, this.length) {
    _eol = fileEditBuilder.changeBuilder.eol;
  }

  /**
   * Create and return an edit representing the replacement of a region of the
   * file with the accumulated text.
   */
  SourceEdit get sourceEdit =>
      new SourceEdit(offset, length, _buffer.toString());

  @override
  void addLinkedEdit(
      String groupName, void buildLinkedEdit(LinkedEditBuilder builder)) {
    LinkedEditBuilderImpl builder = createLinkedEditBuilder();
    int start = offset + _buffer.length;
    try {
      buildLinkedEdit(builder);
    } finally {
      int end = offset + _buffer.length;
      int length = end - start;
      if (length != 0) {
        Position position = new Position(fileEditBuilder.fileEdit.file, start);
        fileEditBuilder.changeBuilder._lockedPositions.add(position);
        LinkedEditGroup group =
            fileEditBuilder.changeBuilder.getLinkedEditGroup(groupName);
        group.addPosition(position, length);
        for (LinkedEditSuggestion suggestion in builder.suggestions) {
          group.addSuggestion(suggestion);
        }
      }
    }
  }

  @override
  void addSimpleLinkedEdit(String groupName, String text,
      {LinkedEditSuggestionKind kind, List<String> suggestions}) {
    addLinkedEdit(groupName, (LinkedEditBuilder builder) {
      builder.write(text);
      if (kind != null && suggestions != null) {
        for (String suggestion in suggestions) {
          builder.addSuggestion(kind, suggestion);
        }
      } else if (kind != null || suggestions != null) {
        throw new ArgumentError(
            'Either both kind and suggestions must be provided or neither.');
      }
    });
  }

  LinkedEditBuilderImpl createLinkedEditBuilder() {
    return new LinkedEditBuilderImpl(this);
  }

  @override
  void selectAll(void writer()) {
    int rangeOffset = _buffer.length;
    writer();
    int rangeLength = _buffer.length - rangeOffset;
    _selectionRange = new SourceRange(offset + rangeOffset, rangeLength);
  }

  @override
  void selectHere() {
    _selectionRange = new SourceRange(offset + _buffer.length, 0);
  }

  @override
  void write(String string) {
    _buffer.write(string);
  }

  @override
  void writeln([String string]) {
    if (string != null) {
      _buffer.write(string);
    }
    if (_eol == null) {
      _buffer.writeln();
    } else {
      _buffer.write(_eol);
    }
  }
}

/**
 * A builder used to build a [SourceFileEdit] within a [SourceChange].
 */
class FileEditBuilderImpl implements FileEditBuilder {
  /**
   * The builder being used to create the source change of which the source file
   * edit will be a part.
   */
  final ChangeBuilderImpl changeBuilder;

  /**
   * The source file edit that is being built.
   */
  final SourceFileEdit fileEdit;

  /**
   * Initialize a newly created builder to build a source file edit within the
   * change being built by the given [changeBuilder]. The file being edited has
   * the given absolute [path] and [timeStamp].
   */
  FileEditBuilderImpl(this.changeBuilder, String path, int timeStamp)
      : fileEdit = new SourceFileEdit(path, timeStamp);

  /**
   * Return `true` if this builder has edits to be applied.
   */
  bool get hasEdits => fileEdit.edits.isNotEmpty;

  @override
  void addDeletion(SourceRange range) {
    EditBuilderImpl builder = createEditBuilder(range.offset, range.length);
    _addEdit(builder);
  }

  @override
  void addInsertion(int offset, void buildEdit(EditBuilder builder)) {
    EditBuilderImpl builder = createEditBuilder(offset, 0);
    try {
      buildEdit(builder);
    } finally {
      _addEdit(builder);
    }
  }

  @override
  void addLinkedPosition(SourceRange range, String groupName) {
    LinkedEditGroup group = changeBuilder.getLinkedEditGroup(groupName);
    Position position = new Position(
        fileEdit.file, range.offset + _deltaToOffset(range.offset));
    group.addPosition(position, range.length);
  }

  @override
  void addReplacement(SourceRange range, void buildEdit(EditBuilder builder)) {
    EditBuilderImpl builder = createEditBuilder(range.offset, range.length);
    try {
      buildEdit(builder);
    } finally {
      _addEdit(builder);
    }
  }

  @override
  void addSimpleInsertion(int offset, String text) {
    EditBuilderImpl builder = createEditBuilder(offset, 0);
    try {
      builder.write(text);
    } finally {
      _addEdit(builder);
    }
  }

  @override
  void addSimpleReplacement(SourceRange range, String text) {
    EditBuilderImpl builder = createEditBuilder(range.offset, range.length);
    try {
      builder.write(text);
    } finally {
      _addEdit(builder);
    }
  }

  EditBuilderImpl createEditBuilder(int offset, int length) {
    return new EditBuilderImpl(this, offset, length);
  }

  /**
   * Finalize the source file edit that is being built.
   */
  Future<void> finalize() async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    // Nothing to do.
  }

  /**
   * Add the edit from the given [builder] to the edits associates with the
   * current file.
   */
  void _addEdit(EditBuilderImpl builder) {
    SourceEdit edit = builder.sourceEdit;
    fileEdit.add(edit);
    int delta = _editDelta(edit);
    changeBuilder._updatePositions(
        edit.offset + math.max<int>(0, delta), delta);
    changeBuilder._lockedPositions.clear();
    _captureSelection(builder, edit);
  }

  /**
   * Capture the selection offset if one was set.
   */
  void _captureSelection(EditBuilderImpl builder, SourceEdit edit) {
    SourceRange range = builder._selectionRange;
    if (range != null) {
      Position position =
          new Position(fileEdit.file, range.offset + _deltaToEdit(edit));
      changeBuilder.setSelection(position);
      changeBuilder._setSelectionRange(range);
    }
  }

  /**
   * Return the current delta caused by edits that will be applied before the
   * [targetEdit]. In other words, if all of the edits that occur before the
   * target edit were to be applied, then the text at the offset of the target
   * edit before the applied edits will be at `offset + _deltaToOffset(offset)`
   * after the edits.
   */
  int _deltaToEdit(SourceEdit targetEdit) {
    int delta = 0;
    for (SourceEdit edit in fileEdit.edits) {
      if (edit.offset < targetEdit.offset) {
        delta += _editDelta(edit);
      }
    }
    return delta;
  }

  /**
   * Return the current delta caused by edits that will be applied before the
   * given [offset]. In other words, if all of the edits that have so far been
   * added were to be applied, then the text at the given `offset` before the
   * applied edits will be at `offset + _deltaToOffset(offset)` after the edits.
   */
  int _deltaToOffset(int offset) {
    int delta = 0;
    for (SourceEdit edit in fileEdit.edits) {
      if (edit.offset <= offset) {
        delta += _editDelta(edit);
      }
    }
    return delta;
  }

  /**
   * Return the delta introduced by the given `edit`.
   */
  int _editDelta(SourceEdit edit) => edit.replacement.length - edit.length;
}

/**
 * A builder used to build a [LinkedEdit] region within an edit.
 */
class LinkedEditBuilderImpl implements LinkedEditBuilder {
  final EditBuilderImpl editBuilder;

  final List<LinkedEditSuggestion> suggestions = <LinkedEditSuggestion>[];

  LinkedEditBuilderImpl(this.editBuilder);

  @override
  void addSuggestion(LinkedEditSuggestionKind kind, String value) {
    suggestions.add(new LinkedEditSuggestion(value, kind));
  }

  @override
  void addSuggestions(LinkedEditSuggestionKind kind, Iterable<String> values) {
    values.forEach((value) => addSuggestion(kind, value));
  }

  @override
  void write(String string) {
    editBuilder.write(string);
  }

  @override
  void writeln([String string]) {
    editBuilder.writeln(string);
  }
}
