// 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`.
  final 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;
  }

  @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,
}
