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

import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';

/// A builder used to build a [SourceChange].
class ChangeBuilderImpl implements ChangeBuilder {
  /// The workspace in which the change builder should operate, or `null` if no
  /// Dart files will be changed.
  final ChangeWorkspace workspace;

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

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

  /// The source change selection or `null` if none.
  Position _selection;

  /// 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 = HashSet<Position>.identity();

  /// A map of absolute normalized path to generic file edit builders.
  final Map<String, FileEditBuilderImpl> _genericFileEditBuilders = {};

  /// A map of absolute normalized path to Dart file edit builders.
  final Map<String, DartFileEditBuilderImpl> _dartFileEditBuilders = {};

  /// Initialize a newly created change builder. If the builder will be used to
  /// create changes for Dart files, then either a [session] or a [workspace]
  /// must be provided (but not both).
  ChangeBuilderImpl(
      {AnalysisSession session, ChangeWorkspace workspace, this.eol})
      : assert(session == null || workspace == null),
        workspace = workspace ?? _SingleSessionWorkspace(session);

  @override
  SourceRange get selectionRange => _selectionRange;

  @override
  SourceChange get sourceChange {
    var change = SourceChange('');
    for (var builder in _genericFileEditBuilders.values) {
      if (builder.hasEdits) {
        change.addFileEdit(builder.fileEdit);
        builder.finalize();
      }
    }
    for (var builder in _dartFileEditBuilders.values) {
      if (builder.hasEdits) {
        change.addFileEdit(builder.fileEdit);
        builder.finalize();
      }
    }
    _linkedEditGroups.forEach((String name, LinkedEditGroup group) {
      change.addLinkedEditGroup(group);
    });
    if (_selection != null) {
      change.selection = _selection;
    }
    return change;
  }

  @override
  Future<void> addDartFileEdit(
      String path, void Function(DartFileEditBuilder builder) buildFileEdit,
      {ImportPrefixGenerator importPrefixGenerator}) async {
    if (_genericFileEditBuilders.containsKey(path)) {
      throw StateError("Can't create both a generic file edit and a dart file "
          'edit for the same file');
    }
    var builder = _dartFileEditBuilders[path];
    if (builder == null) {
      builder = await createDartFileEditBuilder(path);
      if (builder != null) {
        _dartFileEditBuilders[path] = builder;
      }
    }
    if (builder != null) {
      builder.importPrefixGenerator = importPrefixGenerator;
      buildFileEdit(builder);
    }
  }

  @Deprecated('Use either addDartFileEdit or addGenericFileEdit')
  @override
  Future<void> addFileEdit(
      String path, void Function(FileEditBuilder builder) buildFileEdit) async {
    return addGenericFileEdit(path, buildFileEdit);
  }

  @override
  Future<void> addGenericFileEdit(
      String path, void Function(FileEditBuilder builder) buildFileEdit) async {
    if (_dartFileEditBuilders.containsKey(path)) {
      throw StateError("Can't create both a generic file edit and a dart file "
          'edit for the same file');
    }
    var builder = _genericFileEditBuilders[path];
    if (builder == null) {
      builder = await createGenericFileEditBuilder(path);
      if (builder != null) {
        _genericFileEditBuilders[path] = builder;
      }
    }
    if (builder != null) {
      buildFileEdit(builder);
    }
  }

  /// Create and return a [DartFileEditBuilder] that can be used to build edits
  /// to the Dart file with the given [path].
  Future<DartFileEditBuilderImpl> createDartFileEditBuilder(String path) async {
    // TODO(brianwilkerson) Make this method private when
    //  `DartChangeBuilderImpl` is removed.
    if (workspace == null) {
      throw StateError("Can't create a DartFileEditBuilder without providing "
          'either a session or a workspace');
    }
    if (!workspace.containsFile(path)) {
      return null;
    }

    var session = workspace.getSession(path);
    var result = await session.getResolvedUnit(path);
    var state = result?.state ?? ResultState.INVALID_FILE_TYPE;
    if (state == ResultState.INVALID_FILE_TYPE) {
      throw AnalysisException('Cannot analyze "$path"');
    }
    var timeStamp = state == ResultState.VALID ? 0 : -1;

    var declaredUnit = result.unit.declaredElement;
    var libraryUnit = declaredUnit.library.definingCompilationUnit;

    DartFileEditBuilderImpl libraryEditBuilder;
    if (libraryUnit != declaredUnit) {
      // If the receiver is a part file builder, then proactively cache the
      // library file builder so that imports can be finalized synchronously.
      await addDartFileEdit(libraryUnit.source.fullName, (builder) {
        libraryEditBuilder = builder as DartFileEditBuilderImpl;
      });
    }

    return DartFileEditBuilderImpl(this, result, timeStamp, libraryEditBuilder);
  }

  /// Create and return a [FileEditBuilder] that can be used to build edits to
  /// the file with the given [path].
  Future<FileEditBuilderImpl> createGenericFileEditBuilder(String path) async {
    // TODO(brianwilkerson) Make this method private when
    //  `DartChangeBuilderImpl` is removed.
    return 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) {
    var group = _linkedEditGroups[groupName];
    if (group == null) {
      group = LinkedEditGroup.empty();
      _linkedEditGroups[groupName] = group;
    }
    return group;
  }

  @override
  void setSelection(Position position) {
    _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 (var group in _linkedEditGroups.values) {
      for (var position in group.positions) {
        _updatePosition(position);
      }
    }
    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;

  /// The buffer in which the content of the edit is being composed.
  final StringBuffer _buffer = 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 => SourceEdit(offset, length, _buffer.toString());

  @override
  void addLinkedEdit(String groupName,
      void Function(LinkedEditBuilder builder) buildLinkedEdit) {
    var builder = createLinkedEditBuilder();
    var start = offset + _buffer.length;
    try {
      buildLinkedEdit(builder);
    } finally {
      var end = offset + _buffer.length;
      var length = end - start;
      if (length != 0) {
        var position = Position(fileEditBuilder.fileEdit.file, start);
        fileEditBuilder.changeBuilder._lockedPositions.add(position);
        var group = fileEditBuilder.changeBuilder.getLinkedEditGroup(groupName);
        group.addPosition(position, length);
        for (var 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 (var suggestion in suggestions) {
          builder.addSuggestion(kind, suggestion);
        }
      } else if (kind != null || suggestions != null) {
        throw ArgumentError(
            'Either both kind and suggestions must be provided or neither.');
      }
    });
  }

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

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

  @override
  void selectHere() {
    _selectionRange = 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 = SourceFileEdit(path, timeStamp);

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

  @override
  void addDeletion(SourceRange range) {
    if (range.length > 0) {
      var builder = createEditBuilder(range.offset, range.length);
      _addEditBuilder(builder);
    }
  }

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

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

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

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

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

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

  /// Finalize the source file edit that is being built.
  void finalize() {
    // Nothing to do.
  }

  /// Replace edits in the [range] with the given [edit].
  /// The [range] is relative to the original code.
  void replaceEdits(SourceRange range, SourceEdit edit) {
    fileEdit.edits.removeWhere((edit) {
      if (range.contains(edit.offset)) {
        if (!range.contains(edit.end)) {
          throw StateError('$edit is not completely in $range');
        }
        return true;
      } else if (range.contains(edit.end)) {
        throw StateError('$edit is not completely in $range');
      }
      return false;
    });

    _addEdit(edit);
  }

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

  /// Add the edit from the given [builder] to the edits associates with the
  /// current file.
  void _addEditBuilder(EditBuilderImpl builder) {
    var edit = builder.sourceEdit;
    _addEdit(edit);
    _captureSelection(builder, edit);
  }

  /// Capture the selection offset if one was set.
  void _captureSelection(EditBuilderImpl builder, SourceEdit edit) {
    var range = builder._selectionRange;
    if (range != null) {
      var position = 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) {
    var delta = 0;
    for (var 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) {
    var delta = 0;
    for (var 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(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);
  }
}

/// Workspace that wraps a single [AnalysisSession].
class _SingleSessionWorkspace extends ChangeWorkspace {
  final AnalysisSession session;

  _SingleSessionWorkspace(this.session);

  @override
  bool containsFile(String path) {
    var analysisContext = session.analysisContext;
    return analysisContext.contextRoot.isAnalyzed(path);
  }

  @override
  AnalysisSession getSession(String path) {
    if (containsFile(path)) {
      return session;
    }
    throw StateError('Not in a context root: $path');
  }
}
