// 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 'annotated_code_helper.dart';

enum IdKind {
  /// Id used for top level or class members. This is used in [MemberId].
  member,

  /// Id used for classes. This is used in [ClassId].
  cls,

  /// Id used for libraries. This is used in [LibraryId].
  library,

  /// Id used for a code point at certain offset. The id represents the default
  /// use of the code point, often a read access. This is used in [NodeId].
  node,

  /// Id used for an invocation at certain offset. This is used in [NodeId].
  invoke,

  /// Id used for an assignment at certain offset. This is used in [NodeId].
  update,

  /// Id used for the iterator expression of a for-in at certain offset. This is
  /// used in [NodeId].
  iterator,

  /// Id used for the implicit call to `Iterator.current` in a for-in at certain
  /// offset. This is used in [NodeId].
  current,

  /// Id used for the implicit call to `Iterator.moveNext` in a for-in at
  /// certain offset. This is used in [NodeId].
  moveNext,

  /// Id used for the implicit as expression inserted by the compiler.
  implicitAs,

  /// Id used for the statement at certain offset. This is used in [NodeId].
  stmt,

  /// Id used for the error reported at certain offset. This is used in
  /// [NodeId].
  error,
}

/// Id for a code point or element.
abstract class Id {
  IdKind get kind;

  /// Indicates whether the id refers to an element defined outside of the test
  /// case itself (e.g. some tests may need to refer to properties of elements
  /// in `dart:core`).
  bool get isGlobal;

  /// Display name for this id.
  String get descriptor;
}

class IdValue {
  final Id id;
  final Annotation annotation;
  final String value;

  const IdValue(this.id, this.annotation, this.value);

  @override
  int get hashCode => id.hashCode * 13 + value.hashCode * 17;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! IdValue) return false;
    return id == other.id && value == other.value;
  }

  @override
  String toString() => idToString(id, value);

  static String idToString(Id id, String value) {
    switch (id.kind) {
      case IdKind.member:
        MemberId elementId = id;
        return '$memberPrefix${elementId.name}:$value';
      case IdKind.cls:
        ClassId classId = id;
        return '$classPrefix${classId.name}:$value';
      case IdKind.library:
        return '$libraryPrefix$value';
      case IdKind.node:
        return value;
      case IdKind.invoke:
        return '$invokePrefix$value';
      case IdKind.update:
        return '$updatePrefix$value';
      case IdKind.iterator:
        return '$iteratorPrefix$value';
      case IdKind.current:
        return '$currentPrefix$value';
      case IdKind.moveNext:
        return '$moveNextPrefix$value';
      case IdKind.implicitAs:
        return '$implicitAsPrefix$value';
      case IdKind.stmt:
        return '$stmtPrefix$value';
      case IdKind.error:
        return '$errorPrefix$value';
    }
    throw new UnsupportedError("Unexpected id kind: ${id.kind}");
  }

  static const String globalPrefix = "global#";
  static const String memberPrefix = "member: ";
  static const String classPrefix = "class: ";
  static const String libraryPrefix = "library: ";
  static const String invokePrefix = "invoke: ";
  static const String updatePrefix = "update: ";
  static const String iteratorPrefix = "iterator: ";
  static const String currentPrefix = "current: ";
  static const String moveNextPrefix = "moveNext: ";
  static const String implicitAsPrefix = "as: ";
  static const String stmtPrefix = "stmt: ";
  static const String errorPrefix = "error: ";

  static IdValue decode(Uri sourceUri, Annotation annotation, String text,
      {bool preserveWhitespaceInAnnotations: false,
      bool preserveInfixWhitespace: false}) {
    int offset = annotation.offset;
    Id id;
    String expected;
    if (text.startsWith(memberPrefix)) {
      text = text.substring(memberPrefix.length);
      int colonPos = text.indexOf(':');
      if (colonPos == -1) throw "Invalid member id: '$text'";
      String name = text.substring(0, colonPos);
      bool isGlobal = name.startsWith(globalPrefix);
      if (isGlobal) {
        name = name.substring(globalPrefix.length);
      }
      id = new MemberId(name, isGlobal: isGlobal);
      expected = text.substring(colonPos + 1);
    } else if (text.startsWith(classPrefix)) {
      text = text.substring(classPrefix.length);
      int colonPos = text.indexOf(':');
      if (colonPos == -1) throw "Invalid class id: '$text'";
      String name = text.substring(0, colonPos);
      bool isGlobal = name.startsWith(globalPrefix);
      if (isGlobal) {
        name = name.substring(globalPrefix.length);
      }
      id = new ClassId(name, isGlobal: isGlobal);
      expected = text.substring(colonPos + 1);
    } else if (text.startsWith(libraryPrefix)) {
      id = new LibraryId(sourceUri);
      expected = text.substring(libraryPrefix.length);
    } else if (text.startsWith(invokePrefix)) {
      id = new NodeId(offset, IdKind.invoke);
      expected = text.substring(invokePrefix.length);
    } else if (text.startsWith(updatePrefix)) {
      id = new NodeId(offset, IdKind.update);
      expected = text.substring(updatePrefix.length);
    } else if (text.startsWith(iteratorPrefix)) {
      id = new NodeId(offset, IdKind.iterator);
      expected = text.substring(iteratorPrefix.length);
    } else if (text.startsWith(currentPrefix)) {
      id = new NodeId(offset, IdKind.current);
      expected = text.substring(currentPrefix.length);
    } else if (text.startsWith(moveNextPrefix)) {
      id = new NodeId(offset, IdKind.moveNext);
      expected = text.substring(moveNextPrefix.length);
    } else if (text.startsWith(implicitAsPrefix)) {
      id = new NodeId(offset, IdKind.implicitAs);
      expected = text.substring(implicitAsPrefix.length);
    } else if (text.startsWith(stmtPrefix)) {
      id = new NodeId(offset, IdKind.stmt);
      expected = text.substring(stmtPrefix.length);
    } else if (text.startsWith(errorPrefix)) {
      id = new NodeId(offset, IdKind.error);
      expected = text.substring(errorPrefix.length);
    } else {
      id = new NodeId(offset, IdKind.node);
      expected = text;
    }
    if (preserveWhitespaceInAnnotations) {
      // Keep all whitespace.
    } else if (preserveInfixWhitespace) {
      // Remove heading and trailing whitespace.
      expected = expected.trim();
    } else {
      // Remove unneeded whitespace.
      expected = expected.replaceAll(new RegExp(r'\s*(\n\s*)+\s*'), '');
    }
    return new IdValue(id, annotation, expected);
  }
}

/// Id for an member element.
class MemberId implements Id {
  final String className;
  final String memberName;
  @override
  final bool isGlobal;

  factory MemberId(String text, {bool isGlobal: false}) {
    int dotPos = text.indexOf('.');
    if (dotPos != -1) {
      return new MemberId.internal(text.substring(dotPos + 1),
          className: text.substring(0, dotPos), isGlobal: isGlobal);
    } else {
      return new MemberId.internal(text, isGlobal: isGlobal);
    }
  }

  MemberId.internal(this.memberName, {this.className, this.isGlobal: false});

  @override
  int get hashCode => className.hashCode * 13 + memberName.hashCode * 17;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! MemberId) return false;
    return className == other.className && memberName == other.memberName;
  }

  @override
  IdKind get kind => IdKind.member;

  String get name => className != null ? '$className.$memberName' : memberName;

  @override
  String get descriptor => 'member $name';

  @override
  String toString() => 'member:$name';
}

/// Id for a class.
class ClassId implements Id {
  final String className;
  @override
  final bool isGlobal;

  ClassId(this.className, {this.isGlobal: false});

  @override
  int get hashCode => className.hashCode * 13;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! ClassId) return false;
    return className == other.className;
  }

  @override
  IdKind get kind => IdKind.cls;

  String get name => className;

  @override
  String get descriptor => 'class $name';

  @override
  String toString() => 'class:$name';
}

/// Id for a library.
class LibraryId implements Id {
  final Uri uri;

  LibraryId(this.uri);

  // TODO(johnniwinther): Support global library annotations.
  @override
  bool get isGlobal => false;

  @override
  int get hashCode => uri.hashCode * 13;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! LibraryId) return false;
    return uri == other.uri;
  }

  @override
  IdKind get kind => IdKind.library;

  String get name => uri.toString();

  @override
  String get descriptor => 'library $name';

  @override
  String toString() => 'library:$name';
}

/// Id for a code point defined by a kind and a code offset.
class NodeId implements Id {
  final int value;
  @override
  final IdKind kind;

  const NodeId(this.value, this.kind)
      : assert(value != null),
        assert(value >= 0);

  @override
  bool get isGlobal => false;

  @override
  int get hashCode => value.hashCode * 13 + kind.hashCode * 17;

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! NodeId) return false;
    return value == other.value && kind == other.kind;
  }

  @override
  String get descriptor => 'offset $value ($kind)';

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

class ActualData<T> {
  final Id id;
  final T value;
  final Uri uri;
  final int _offset;
  final Object object;

  ActualData(this.id, this.value, this.uri, this._offset, this.object);

  int get offset {
    if (id is NodeId) {
      NodeId nodeId = id;
      return nodeId.value;
    } else {
      return _offset;
    }
  }

  String get objectText {
    return 'object `${'$object'.replaceAll('\n', '')}` (${object.runtimeType})';
  }

  @override
  String toString() => 'ActualData(id=$id,value=$value,uri=$uri,'
      'offset=$offset,object=$objectText)';
}

abstract class DataRegistry<T> {
  Map<Id, ActualData<T>> get actualMap;

  /// Registers [value] with [id] in [actualMap].
  ///
  /// Checks for duplicate data for [id].
  void registerValue(Uri uri, int offset, Id id, T value, Object object) {
    if (value != null) {
      ActualData<T> newData = new ActualData<T>(id, value, uri, offset, object);
      if (actualMap.containsKey(id)) {
        ActualData<T> existingData = actualMap[id];
        ActualData<T> mergedData = mergeData(existingData, newData);
        if (mergedData != null) {
          actualMap[id] = mergedData;
        } else {
          report(
              uri,
              offset,
              "Duplicate id ${id}, value=$value, object=$object "
              "(${object.runtimeType})");
          report(
              uri,
              offset,
              "Duplicate id ${id}, value=${existingData.value}, "
              "object=${existingData.object} "
              "(${existingData.object.runtimeType})");
          fail("Duplicate id $id.");
        }
      } else {
        actualMap[id] = newData;
      }
    }
  }

  ActualData<T> mergeData(ActualData<T> value1, ActualData<T> value2) => null;

  /// Called to report duplicate errors.
  void report(Uri uri, int offset, String message);

  /// Called to raise an exception on duplicate errors.
  void fail(String message);
}
