// 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 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/generated/utilities_general.dart';

/// Description of a failure to find a valid override from superinterfaces.
class Conflict {
  /// The name of an instance member for which we failed to find a valid
  /// override.
  final Name name;

  /// The list of candidates for a valid override for a member [name].  It has
  /// at least two items, because otherwise the only candidate is always valid.
  final List<FunctionType> candidates;

  /// The getter that conflicts with the [method], or `null`, if the conflict
  /// is inconsistent inheritance.
  final FunctionType getter;

  /// The method tha conflicts with the [getter], or `null`, if the conflict
  /// is inconsistent inheritance.
  final FunctionType method;

  Conflict(this.name, this.candidates, [this.getter, this.method]);
}

/// Manages knowledge about interface types and their members.
class InheritanceManager2 {
  static final _noSuchMethodName = Name(null, 'noSuchMethod');

  final TypeSystem _typeSystem;

  /// Cached instance interfaces for [InterfaceType].
  final Map<InterfaceType, Interface> _interfaces = {};

  /// The set of classes that are currently being processed, used to detect
  /// self-referencing cycles.
  final Set<ClassElement> _processingClasses = new Set<ClassElement>();

  InheritanceManager2(this._typeSystem);

  /// Return the member with the given [name] that the [type] inherits from the
  /// mixins, superclasses, or interfaces; or `null` if no member is inherited.
  FunctionType getInherited(InterfaceType type, Name name) {
    return getOverridden(type, name)?.last;
  }

  /// Return the interface of the given [type].  It might include private
  /// members, not necessary accessible in all libraries.
  Interface getInterface(InterfaceType type) {
    if (type == null) {
      return Interface._empty;
    }

    var result = _interfaces[type];
    if (result != null) {
      return result;
    }
    _interfaces[type] = Interface._empty;

    var classElement = type.element;
    if (!_processingClasses.add(classElement)) {
      return Interface._empty;
    }

    Map<Name, List<FunctionType>> namedCandidates = {};
    List<Map<Name, FunctionType>> superImplemented = [];
    Map<Name, FunctionType> declared;
    Interface superInterface;
    Map<Name, FunctionType> implemented;
    Map<Name, FunctionType> implementedForMixing;
    try {
      // If a class declaration has a member declaration, the signature of that
      // member declaration becomes the signature in the interface.
      declared = _getTypeMembers(type);

      for (var interface in type.interfaces) {
        var interfaceObj = getInterface(interface);
        _addCandidates(namedCandidates, interfaceObj);
      }

      if (classElement.isMixin) {
        for (var constraint in type.superclassConstraints) {
          var interfaceObj = getInterface(constraint);
          _addCandidates(namedCandidates, interfaceObj);
        }

        implemented = {};

        // `mixin M on S1, S2 {}` can call using `super` any instance member
        // from its superclass constraints, whether it is abstract or concrete.
        Map<Name, FunctionType> mixinSuperClass = {};
        _findMostSpecificFromNamedCandidates(mixinSuperClass, namedCandidates);
        superImplemented.add(mixinSuperClass);
      } else {
        if (type.superclass != null) {
          superInterface = getInterface(type.superclass);
          _addCandidates(namedCandidates, superInterface);

          implemented = superInterface.implemented;
          superImplemented.add(implemented);
        } else {
          implemented = {};
        }

        implementedForMixing = {};
        for (var mixin in type.mixins) {
          var interfaceObj = getInterface(mixin);
          _addCandidates(namedCandidates, interfaceObj);

          implemented = <Name, FunctionType>{}
            ..addAll(implemented)
            ..addAll(interfaceObj.implementedForMixing);
          superImplemented.add(implemented);
          implementedForMixing.addAll(interfaceObj.implementedForMixing);
        }
      }
    } finally {
      _processingClasses.remove(classElement);
    }

    var thisImplemented = <Name, FunctionType>{};
    _addImplemented(thisImplemented, type);

    if (classElement.isMixin) {
      implementedForMixing = thisImplemented;
    } else {
      implementedForMixing.addAll(thisImplemented);
    }

    implemented = <Name, FunctionType>{}..addAll(implemented);
    _addImplemented(implemented, type);

    // If a class declaration does not have a member declaration with a
    // particular name, but some super-interfaces do have a member with that
    // name, it's a compile-time error if there is no signature among the
    // super-interfaces that is a valid override of all the other
    // super-interface signatures with the same name. That "most specific"
    // signature becomes the signature of the class's interface.
    Map<Name, FunctionType> map = new Map.of(declared);
    List<Conflict> conflicts = _findMostSpecificFromNamedCandidates(
      map,
      namedCandidates,
    );

    var noSuchMethodForwarders = Set<Name>();
    if (classElement.isAbstract) {
      if (superInterface != null) {
        noSuchMethodForwarders = superInterface.noSuchMethodForwarders;
      }
    } else {
      var noSuchMethod = implemented[_noSuchMethodName]?.element;
      if (noSuchMethod != null && !_isDeclaredInObject(noSuchMethod)) {
        var superForwarders = superInterface?.noSuchMethodForwarders;
        for (var name in map.keys) {
          if (!implemented.containsKey(name) ||
              superForwarders != null && superForwarders.contains(name)) {
            implemented[name] = map[name];
            noSuchMethodForwarders.add(name);
          }
        }
      }
    }

    var interface = new Interface._(
      map,
      declared,
      implemented,
      noSuchMethodForwarders,
      implementedForMixing,
      namedCandidates,
      superImplemented,
      conflicts ?? const [],
    );
    _interfaces[type] = interface;
    return interface;
  }

  /// Return the member with the given [name].
  ///
  /// If [concrete] is `true`, the the concrete implementation is returned,
  /// from the given [type], or its superclass.
  ///
  /// If [forSuper] is `true`, then [concrete] is implied, and only concrete
  /// members from the superclass are considered.
  ///
  /// If [forMixinIndex] is specified, only the nominal superclass, and the
  /// given number of mixins after it are considered.  For example for `1` in
  /// `class C extends S with M1, M2, M3`, only `S` and `M1` are considered.
  FunctionType getMember(
    InterfaceType type,
    Name name, {
    bool concrete: false,
    int forMixinIndex: -1,
    bool forSuper: false,
  }) {
    var interface = getInterface(type);
    if (forSuper) {
      var superImplemented = interface._superImplemented;
      if (forMixinIndex >= 0) {
        return superImplemented[forMixinIndex][name];
      }
      return superImplemented.last[name];
    }
    if (concrete) {
      return interface.implemented[name];
    }
    return interface.map[name];
  }

  /// Return all members of mixins, superclasses, and interfaces that a member
  /// with the given [name], defined in the [type], would override; or `null`
  /// if no members would be overridden.
  List<FunctionType> getOverridden(InterfaceType type, Name name) {
    var interface = getInterface(type);
    return interface._overridden[name];
  }

  void _addCandidate(Map<Name, List<FunctionType>> namedCandidates, Name name,
      FunctionType candidate) {
    var candidates = namedCandidates[name];
    if (candidates == null) {
      candidates = <FunctionType>[];
      namedCandidates[name] = candidates;
    }

    candidates.add(candidate);
  }

  void _addCandidates(
      Map<Name, List<FunctionType>> namedCandidates, Interface interface) {
    var map = interface.map;
    for (var name in map.keys) {
      var candidate = map[name];
      _addCandidate(namedCandidates, name, candidate);
    }
  }

  void _addImplemented(
      Map<Name, FunctionType> implemented, InterfaceType type) {
    var libraryUri = type.element.librarySource.uri;

    void addMember(ExecutableElement member) {
      if (!member.isAbstract && !member.isStatic) {
        var name = new Name(libraryUri, member.name);
        implemented[name] = member.type;
      }
    }

    void addMembers(InterfaceType type) {
      type.methods.forEach(addMember);
      type.accessors.forEach(addMember);
    }

    addMembers(type);
  }

  /// Check that all [candidates] for the given [name] have the same kind, all
  /// getters, all methods, or all setter.  If a conflict found, return the
  /// new [Conflict] instance that describes it.
  Conflict _checkForGetterMethodConflict(
      Name name, List<FunctionType> candidates) {
    assert(candidates.length > 1);

    bool allGetters = true;
    bool allMethods = true;
    bool allSetters = true;
    for (var candidate in candidates) {
      var kind = candidate.element.kind;
      if (kind != ElementKind.GETTER) {
        allGetters = false;
      }
      if (kind != ElementKind.METHOD) {
        allMethods = false;
      }
      if (kind != ElementKind.SETTER) {
        allSetters = false;
      }
    }

    if (allGetters || allMethods || allSetters) {
      return null;
    }

    FunctionType getterType;
    FunctionType methodType;
    for (var candidate in candidates) {
      var kind = candidate.element.kind;
      if (kind == ElementKind.GETTER) {
        getterType ??= candidate;
      }
      if (kind == ElementKind.METHOD) {
        methodType ??= candidate;
      }
    }
    return new Conflict(name, candidates, getterType, methodType);
  }

  /// The given [namedCandidates] maps names to candidates from direct
  /// superinterfaces.  Find the most specific signature, and put it into the
  /// [map], if there is no one yet (from the class itself).  If there is no
  /// such single most specific signature (i.e. no valid override), then add a
  /// new conflict description.
  List<Conflict> _findMostSpecificFromNamedCandidates(
      Map<Name, FunctionType> map,
      Map<Name, List<FunctionType>> namedCandidates) {
    List<Conflict> conflicts = null;

    for (var name in namedCandidates.keys) {
      if (map.containsKey(name)) {
        continue;
      }

      var candidates = namedCandidates[name];

      // If just one candidate, it is always valid.
      if (candidates.length == 1) {
        map[name] = candidates[0];
        continue;
      }

      // Check for a getter/method conflict.
      var conflict = _checkForGetterMethodConflict(name, candidates);
      if (conflict != null) {
        conflicts ??= <Conflict>[];
        conflicts.add(conflict);
      }

      // Candidates are recorded in forward order, so
      // `class X extends S with M1, M2 implements I1, I2 {}` will record
      // candidates from [I1, I2, S, M1, M2]. But during method lookup
      // candidates should be considered in backward order, i.e. from `M2`,
      // then from `M1`, then from `S`.
      FunctionType validOverride;
      for (var i = candidates.length - 1; i >= 0; i--) {
        validOverride = candidates[i];
        for (var j = 0; j < candidates.length; j++) {
          var candidate = candidates[j];
          if (!_typeSystem.isOverrideSubtypeOf(validOverride, candidate)) {
            validOverride = null;
            break;
          }
        }
        if (validOverride != null) {
          break;
        }
      }

      if (validOverride != null) {
        map[name] = validOverride;
      } else {
        conflicts ??= <Conflict>[];
        conflicts.add(new Conflict(name, candidates));
      }
    }

    return conflicts;
  }

  Map<Name, FunctionType> _getTypeMembers(InterfaceType type) {
    var declared = <Name, FunctionType>{};
    var libraryUri = type.element.librarySource.uri;

    var methods = type.methods;
    for (var i = 0; i < methods.length; i++) {
      var method = methods[i];
      if (!method.isStatic) {
        var name = new Name(libraryUri, method.name);
        declared[name] = method.type;
      }
    }

    var accessors = type.accessors;
    for (var i = 0; i < accessors.length; i++) {
      var accessor = accessors[i];
      if (!accessor.isStatic) {
        var name = new Name(libraryUri, accessor.name);
        declared[name] = accessor.type;
      }
    }

    return declared;
  }

  static bool _isDeclaredInObject(ExecutableElement element) {
    var enclosing = element.enclosingElement;
    return enclosing is ClassElement &&
        enclosing.supertype == null &&
        !enclosing.isMixin;
  }
}

/// The instance interface of an [InterfaceType].
class Interface {
  static final _empty = Interface._(
    const {},
    const {},
    const {},
    Set<Name>(),
    const {},
    const {},
    const [{}],
    const [],
  );

  /// The map of names to their signature in the interface.
  final Map<Name, FunctionType> map;

  /// The map of declared names to their signatures.
  final Map<Name, FunctionType> declared;

  /// The map of names to their concrete implementations.
  final Map<Name, FunctionType> implemented;

  /// The set of names that are `noSuchMethod` forwarders in [implemented].
  final Set<Name> noSuchMethodForwarders;

  /// The map of names to their concrete implementations that can be mixed
  /// when this type is used as a mixin.
  final Map<Name, FunctionType> implementedForMixing;

  /// The map of names to their signatures from the mixins, superclasses,
  /// or interfaces.
  final Map<Name, List<FunctionType>> _overridden;

  /// Each item of this list maps names to their concrete implementations.
  /// The first item of the list is the nominal superclass, next the nominal
  /// superclass plus the first mixin, etc. So, for the class like
  /// `class C extends S with M1, M2`, we get `[S, S&M1, S&M1&M2]`.
  final List<Map<Name, FunctionType>> _superImplemented;

  /// The list of conflicts between superinterfaces - the nominal superclass,
  /// mixins, and interfaces.  Does not include conflicts with the declared
  /// members of the class.
  final List<Conflict> conflicts;

  Interface._(
    this.map,
    this.declared,
    this.implemented,
    this.noSuchMethodForwarders,
    this.implementedForMixing,
    this._overridden,
    this._superImplemented,
    this.conflicts,
  );
}

/// A public name, or a private name qualified by a library URI.
class Name {
  /// If the name is private, the URI of the defining library.
  /// Otherwise, it is `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;

  /// Precomputed
  final bool isPublic;

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

  factory Name(Uri libraryUri, String name) {
    if (name.startsWith('_')) {
      var hashCode = JenkinsSmiHash.hash2(libraryUri.hashCode, name.hashCode);
      return new Name._internal(libraryUri, name, false, hashCode);
    } else {
      return new Name._internal(null, name, true, name.hashCode);
    }
  }

  Name._internal(this.libraryUri, this.name, this.isPublic, this.hashCode);

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

  bool isAccessibleFor(Uri libraryUri) {
    return isPublic || this.libraryUri == libraryUri;
  }

  @override
  String toString() => libraryUri != null ? '$libraryUri::$name' : name;
}
