// Copyright (c) 2018, 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:typed_data';

import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:convert/convert.dart';

/// The reference to a class member.
class ClassMemberReference {
  /// The target class name.
  ///
  /// This is different from the class that actually turned out to define
  /// the referenced member at the time of recording this reference. So, we
  /// will notice added overrides in the target class, or anywhere in between.
  final LibraryQualifiedName target;

  /// The name referenced in the [target].
  final String name;

  @override
  final int hashCode;

  ClassMemberReference(this.target, this.name)
      : hashCode = JenkinsSmiHash.hash2(target.hashCode, name.hashCode);

  @override
  bool operator ==(other) {
    return other is ClassMemberReference &&
        other.target == target &&
        other.name == name;
  }

  @override
  String toString() {
    return '($target, $name)';
  }

  static int compare(ClassMemberReference first, ClassMemberReference second) {
    var result = LibraryQualifiedName.compare(first.target, second.target);
    if (result != 0) return result;

    return first.name.compareTo(second.name);
  }
}

/// The dependencies of the API or implementation portion of a node.
class Dependencies {
  static final none = Dependencies([], [], [], [], [], []);

  /// The token signature of this portion of the node. It depends on all
  /// tokens that might affect the node API or implementation resolution.
  final List<int> tokenSignature;

  /// The names that appear unprefixed in this portion of the node, and are
  /// not defined locally in the node. Locally defined names themselves
  /// depend on some non-local nodes, which will also recorded here.
  ///
  /// This list is sorted.
  final List<String> unprefixedReferencedNames;

  /// The names of import prefixes used to reference names in this node.
  ///
  /// This list is sorted.
  final List<String> importPrefixes;

  /// The names referenced by this node with the import prefix at the
  /// corresponding index in [importPrefixes].
  ///
  /// This list is sorted.
  final List<List<String>> importPrefixedReferencedNames;

  /// The names that appear prefixed with `super` in this portion of the node.
  ///
  /// This list is sorted.
  final List<String> superReferencedNames;

  /// The class members referenced in this portion of the node.
  ///
  /// This list is sorted.
  final List<ClassMemberReference> classMemberReferences;

  /// All referenced nodes, computed from [unprefixedReferencedNames],
  /// [importPrefixedReferencedNames], and [classMemberReferences].
  List<Node> referencedNodes;

  /// The transitive signature of this portion of the node, computed using
  /// the [tokenSignature] of this node, and API signatures of the
  /// [referencedNodes].
  List<int> transitiveSignature;

  Dependencies(
      this.tokenSignature,
      this.unprefixedReferencedNames,
      this.importPrefixes,
      this.importPrefixedReferencedNames,
      this.superReferencedNames,
      this.classMemberReferences);

  String get tokenSignatureHex => hex.encode(tokenSignature);
}

/// A name qualified by a library URI.
class LibraryQualifiedName {
  /// The URI of the defining library.
  /// Not `null`.
  final Uri libraryUri;

  /// The name of this name object.
  /// If the name starts with `_`, then the name is private.
  /// Names of setters end with `=`.
  final String name;

  /// Whether this name is private, and its [name] starts with `_`.
  final bool isPrivate;

  /// The cached, pre-computed hash code.
  @override
  final int hashCode;

  factory LibraryQualifiedName(Uri libraryUri, String name) {
    var isPrivate = name.startsWith('_');
    var hashCode = JenkinsSmiHash.hash2(libraryUri.hashCode, name.hashCode);
    return LibraryQualifiedName._internal(
        libraryUri, name, isPrivate, hashCode);
  }

  LibraryQualifiedName._internal(
      this.libraryUri, this.name, this.isPrivate, this.hashCode);

  @override
  bool operator ==(Object other) {
    return other is LibraryQualifiedName &&
        other.hashCode == hashCode &&
        name == other.name &&
        libraryUri == other.libraryUri;
  }

  /// Whether this name us accessible for the library with the given
  /// [libraryUri], i.e. when the name is public, or is defined in a library
  /// with the same URI.
  bool isAccessibleFor(Uri libraryUri) {
    return !isPrivate || this.libraryUri == libraryUri;
  }

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

  /// Compare given names by their raw names.
  ///
  /// This method should be used only for sorting, it does not follow the
  /// complete semantics of [==] and [hashCode].
  static int compare(LibraryQualifiedName first, LibraryQualifiedName second) {
    return first.name.compareTo(second.name);
  }
}

/// A dependency node - anything that has a name, and can be referenced.
class Node {
  /// The API or implementation signature used in [Dependencies]
  /// as a marker that this node is changed, explicitly because its token
  /// signature changed, or implicitly - because it references a changed node.
  static final changedSignature = Uint8List.fromList([0xDE, 0xAD, 0xBE, 0xEF]);

  final LibraryQualifiedName name;
  final NodeKind kind;

  /// Dependencies that affect the API of the node, so affect API or
  /// implementation dependencies of the nodes that use this node.
  final Dependencies api;

  /// Additional (to the [api]) dependencies that affect only the
  /// "implementation" of the node, e.g. the body of a method, but are not
  /// visible outside of the node, and so don't affect any other nodes.
  final Dependencies impl;

  /// If the node is a class member, the node of the enclosing class.
  /// Otherwise `null`.
  final Node enclosingClass;

  /// If the node is a class, the nodes of its type parameters.
  /// Otherwise `null`.
  List<Node> classTypeParameters;

  /// If the node is a class, the sorted list of members in this class.
  /// Otherwise `null`.
  List<Node> classMembers;

  Node(this.name, this.kind, this.api, this.impl,
      {this.enclosingClass, this.classTypeParameters});

  /// Return the node that can be referenced by the given [name] from the
  /// library with the given [libraryUri].
  Node getClassMember(Uri libraryUri, String name) {
    // TODO(scheglov) The list is sorted, use this fact to search faster.
    // TODO(scheglov) Collect superclass members here or outside.
    for (var i = 0; i < classMembers.length; ++i) {
      var member = classMembers[i];
      var memberName = member.name;
      if (memberName.name == name && memberName.isAccessibleFor(libraryUri)) {
        return member;
      }
    }
    return null;
  }

  /// Set new class members for this class.
  void setClassMembers(List<Node> newClassMembers) {
    classMembers = newClassMembers;
  }

  /// Set new class type parameters for this class.
  void setTypeParameters(List<Node> newTypeParameters) {
    classTypeParameters = newTypeParameters;
  }

  @override
  String toString() {
    if (enclosingClass != null) {
      return '$enclosingClass::${name.name}';
    }
    return name.toString();
  }

  /// Compare given nodes by their names.
  static int compare(Node first, Node second) {
    return LibraryQualifiedName.compare(first.name, second.name);
  }
}

/// Kinds of nodes.
enum NodeKind {
  CLASS,
  CLASS_TYPE_ALIAS,
  CONSTRUCTOR,
  ENUM,
  FUNCTION,
  FUNCTION_TYPE_ALIAS,
  GENERIC_TYPE_ALIAS,
  GETTER,
  METHOD,
  MIXIN,
  SETTER,
  TYPE_PARAMETER,
}
