// 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.

part of elements;

/// A [Name] represents the abstraction of a Dart identifier which takes privacy
/// and setter into account.
// TODO(johnniwinther): Try to share logic with [Selector].
abstract class Name {
  /// Create a [Name] for an identifier [text]. If [text] begins with '_' a
  /// private name with respect to [library] is created. If [isSetter] is `true`
  /// the created name represents the setter name 'text='.
  factory Name(String text, LibraryElement library, {bool isSetter: false}) {
    if (isPrivateName(text)) {
      return new PrivateName(text, library, isSetter: isSetter);
    }
    return new PublicName(text, isSetter: isSetter);
  }

  /// The text of the name without prefixed library name or suffixed '=' if
  /// applicable.
  String get text;

  /// Is `true` if this name represents the name of a setter.
  bool get isSetter;

  /// Returns the getter name corresponding to this name. If this name is a
  /// setter name 'v=' then the name 'v' is returned, otherwise the name itself
  /// is returned.
  Name get getter;

  /// Returns the seeter name corresponding to this name. If this name is a
  /// getter name 'v' then the name 'v=' is returned, otherwsie the name itself
  /// is returned.
  Name get setter;

  /// Returns `true` if an entity of this name is accessible from library
  /// [element].
  bool isAccessibleFrom(LibraryElement element);

  /// Returns `true` if this name is private.
  bool get isPrivate;

  /// Returns `true` if this name is the same as [other] not taking the library
  /// privacy into account.
  bool isSimilarTo(Name other);
  int get similarHashCode;

  LibraryElement get library;


  /// Returns `true` when [s] is private if used as an identifier.
  static bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;

  /// Returns `true` when [s] is public if used as an identifier.
  static bool isPublicName(String s) => !isPrivateName(s);
}

class PublicName implements Name {
  final String text;
  final bool isSetter;

  const PublicName(this.text, {this.isSetter: false});

  Name get getter => isSetter ? new PublicName(text) : this;

  Name get setter => isSetter ? this : new PublicName(text, isSetter: true);

  bool isAccessibleFrom(LibraryElement element) => true;

  bool get isPrivate => false;

  int get hashCode => similarHashCode;

  bool operator ==(other) {
    if (other is! PublicName) return false;
    return isSimilarTo(other);
  }

  bool isSimilarTo(Name other) =>
      text == other.text && isSetter == other.isSetter;
  int get similarHashCode => text.hashCode + 11 * isSetter.hashCode;

  LibraryElement get library => null;

  String toString() => isSetter ? '$text=' : text;
}

class PrivateName extends PublicName {
  final LibraryElement library;

  PrivateName(String text, this.library, {bool isSetter: false})
      : super(text, isSetter: isSetter);

  Name get getter => isSetter ? new PrivateName(text, library) : this;

  Name get setter {
    return isSetter ? this : new PrivateName(text, library, isSetter: true);
  }

  bool isAccessibleFrom(LibraryElement element) => library == element;

  bool get isPrivate => true;

  int get hashCode => super.hashCode + 13 * library.hashCode;

  bool operator ==(other) {
    if (other is! PrivateName) return false;
    return super==(other) && library == other.library;
  }

  String toString() => '${library.libraryName}#${super.toString()}';
}
