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

library services.correction.change;

import 'package:analysis_services/constants.dart';
import 'package:analysis_services/json.dart';
import 'package:analyzer/src/generated/source.dart';


/**
 * A description of a single change to one or more files. 
 */
class Change implements HasToJson {
  /**
   * A textual description of the change to be applied. 
   */
  final String message;

  /**
   * A list of the [FileEdit]s used to effect the change. 
   */
  final List<FileEdit> fileEdits = <FileEdit>[];

  /**
   * A list of the [LinkedEditGroup]s in the change. 
   */
  final List<LinkedEditGroup> linkedEditGroups = <LinkedEditGroup>[];

  /**
   * The position that should be selected after the edits have been applied.
   */
  Position selection;

  Change(this.message);

  /**
   * Adds [edit] to the [FileEdit] for the given [file].
   */
  void addEdit(String file, Edit edit) {
    FileEdit fileEdit = getFileEdit(file);
    if (fileEdit == null) {
      fileEdit = new FileEdit(file);
      addFileEdit(fileEdit);
    }
    fileEdit.add(edit);
  }

  /**
   * Adds the given [FileEdit].
   */
  void addFileEdit(FileEdit edit) {
    fileEdits.add(edit);
  }

  /**
   * Adds the given [LinkedEditGroup].
   */
  void addLinkedEditGroup(LinkedEditGroup linkedEditGroup) {
    linkedEditGroups.add(linkedEditGroup);
  }

  /**
   * Returns the [FileEdit] for the given [file], maybe `null`.
   */
  FileEdit getFileEdit(String file) {
    for (FileEdit fileEdit in fileEdits) {
      if (fileEdit.file == file) {
        return fileEdit;
      }
    }
    return null;
  }

  @override
  Map<String, Object> toJson() {
    Map<String, Object> json = {
      MESSAGE: message,
      EDITS: objectToJson(fileEdits),
      LINKED_EDIT_GROUPS: objectToJson(linkedEditGroups)
    };
    if (selection != null) {
      json[SELECTION] = selection.toJson();
    }
    return json;
  }

  @override
  String toString() =>
      'Change(message=$message, edits=$fileEdits, '
          'linkedEditGroups=$linkedEditGroups, selection=$selection)';
}


/**
 * A description of a single change to a single file. 
 */
class Edit implements HasToJson {
  /**
   * The offset of the region to be modified. 
   */
  final int offset;

  /**
   * The length of the region to be modified.
   */
  final int length;

  /**
   * The text that is to replace the specified region in the original text. 
   */
  final String replacement;

  Edit(this.offset, this.length, this.replacement);

  Edit.range(SourceRange range, String replacement) : this(
      range.offset,
      range.length,
      replacement);

  /**
   * The offset of a character immediately after the region to be modified. 
   */
  int get end => offset + length;

  bool operator ==(other) {
    if (other is Edit) {
      return other.offset == offset &&
          other.length == length &&
          other.replacement == replacement;
    }
    return false;
  }

  @override
  Map<String, Object> toJson() {
    return {
      OFFSET: offset,
      LENGTH: length,
      REPLACEMENT: replacement
    };
  }

  @override
  String toString() =>
      "Edit(offset=$offset, length=$length, replacement=:>$replacement<:)";
}


/**
 * A description of a set of changes to a single file. 
 */
class FileEdit implements HasToJson {
  /**
   * The file to be modified.
   */
  final String file;

  /**
   * A list of the [Edit]s used to effect the change. 
   */
  final List<Edit> edits = <Edit>[];

  FileEdit(this.file);

  /**
   * Adds the given [Edit] to the list.
   */
  void add(Edit edit) {
    edits.add(edit);
  }

  @override
  Map<String, Object> toJson() {
    return {
      FILE: file,
      EDITS: objectToJson(edits)
    };
  }

  @override
  String toString() => "FileEdit(file=$file, edits=$edits)";
}


/**
 * A group of linked [Position]s in multiple files that are simultaneously
 * modified - if one gets edited, all other positions in a group are edited the
 * same way. All linked positions in a group have the same content.
 */
class LinkedEditGroup implements HasToJson {
  final String id;
  int length;
  final List<Position> positions = <Position>[];
  final List<LinkedEditSuggestion> suggestions = <LinkedEditSuggestion>[];

  LinkedEditGroup(this.id);

  void addPosition(Position position, int length) {
    positions.add(position);
    this.length = length;
  }

  void addSuggestion(LinkedEditSuggestion suggestion) {
    suggestions.add(suggestion);
  }

  @override
  Map<String, Object> toJson() {
    return {
      ID: id,
      LENGTH: length,
      POSITIONS: objectToJson(positions),
      SUGGESTIONS: objectToJson(suggestions)
    };
  }

  @override
  String toString() =>
      'LinkedEditGroup(id=$id, length=$length, '
          'positions=$positions, suggestions=$suggestions)';
}


/**
 * A suggestion of a value that could be used to replace all of the linked edit
 * regions in a [LinkedEditGroup].
 */
class LinkedEditSuggestion implements HasToJson {
  final LinkedEditSuggestionKind kind;
  final String value;

  LinkedEditSuggestion(this.kind, this.value);

  bool operator ==(other) {
    if (other is LinkedEditSuggestion) {
      return other.kind == kind && other.value == value;
    }
    return false;
  }

  @override
  Map<String, Object> toJson() {
    return {
      KIND: kind.name,
      VALUE: value
    };
  }

  @override
  String toString() => '(kind=$kind, value=$value)';
}


/**
 * An enumeration of the kind of values that can be suggested for a linked edit.
 */
class LinkedEditSuggestionKind {
  static const METHOD = const LinkedEditSuggestionKind('METHOD');
  static const PARAMETER = const LinkedEditSuggestionKind('PARAMETER');
  static const TYPE = const LinkedEditSuggestionKind('TYPE');
  static const VARIABLE = const LinkedEditSuggestionKind('VARIABLE');
  final String name;

  const LinkedEditSuggestionKind(this.name);

  @override
  String toString() => name;
}


/**
 * A position in a file.
 */
class Position implements HasToJson {
  final String file;
  final int offset;

  Position(this.file, this.offset);

  int get hashCode {
    int hash = file.hashCode;
    hash = hash * 31 + offset;
    return hash;
  }

  bool operator ==(other) {
    if (other is Position) {
      return other.file == file && other.offset == offset;
    }
    return false;
  }

  @override
  Map<String, Object> toJson() {
    return {
      FILE: file,
      OFFSET: offset
    };
  }

  @override
  String toString() => 'Position(file=$file, offset=$offset)';
}
