// Copyright (c) 2012, 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.

library;

import '../common/names.dart' show Identifiers, Selectors;
import '../elements/entities.dart';
import '../elements/names.dart';
import '../inferrer/abstract_value_domain.dart';
import '../util/util.dart' show Hashing, Setlet;
import 'selector.dart' show Selector;

// TODO(kasperl): This actually holds getters and setters just fine
// too and strictly they aren't functions. Maybe this needs a better
// name -- something like ElementSet seems a bit too generic.
class FunctionSet {
  final Map<String, FunctionSetNode> _publicNodes;
  final Map<Uri, Map<String, FunctionSetNode>> _privateNodes;

  factory FunctionSet(Iterable<MemberEntity> liveInstanceMembers) {
    Map<String, FunctionSetNode> publicNodes = {};
    Map<Uri, Map<String, FunctionSetNode>> privateNodes = {};
    for (MemberEntity member in liveInstanceMembers) {
      String name = member.name!;
      if (member.memberName.isPrivate) {
        final uri = member.memberName.uri!;
        ((privateNodes[uri] ??= {})[name] ??= FunctionSetNode()).add(member);
      } else {
        (publicNodes[name] ??= FunctionSetNode()).add(member);
      }
    }
    return FunctionSet.internal(publicNodes, privateNodes);
  }

  FunctionSet.internal(this._publicNodes, this._privateNodes);

  /// Returns all the functions that may be invoked with the [selector] on a
  /// receiver with the given [constraint]. The returned elements may include
  /// noSuchMethod handlers that are potential targets indirectly through the
  /// noSuchMethod mechanism.
  Iterable<MemberEntity> filter(
    Selector selector,
    AbstractValue? receiver,
    AbstractValueDomain domain,
  ) {
    return query(selector, receiver, domain).functions;
  }

  SelectorMask _createSelectorMask(
    Selector selector,
    AbstractValue? receiver,
    AbstractValueDomain domain,
  ) {
    return receiver != null
        ? SelectorMask(selector, receiver)
        : SelectorMask(selector, domain.dynamicType);
  }

  /// Returns the set of functions that can be the target of a call to
  /// [selector] on a receiver constrained by [constraint] including
  /// 'noSuchMethod' methods where applicable.
  FunctionSetQuery query(
    Selector selector,
    AbstractValue? receiver,
    AbstractValueDomain domain,
  ) {
    Name name = selector.memberName;
    SelectorMask selectorMask = _createSelectorMask(selector, receiver, domain);
    SelectorMask noSuchMethodMask = SelectorMask(
      Selectors.noSuchMethod_,
      selectorMask.receiver,
    );
    FunctionSetNode? node;
    if (name.isPrivate) {
      final forUri = _privateNodes[name.uri];
      if (forUri != null) node = forUri[name.text];
    } else {
      node = _publicNodes[name.text];
    }
    FunctionSetNode? noSuchMethods = _publicNodes[Identifiers.noSuchMethod_];
    if (node != null) {
      return node.query(selectorMask, domain, noSuchMethods, noSuchMethodMask);
    }
    // If there is no method that matches [selector] we know we can
    // only hit [:noSuchMethod:].
    if (noSuchMethods == null) {
      return const EmptyFunctionSetQuery();
    }
    return noSuchMethods.query(noSuchMethodMask, domain);
  }
}

/// A selector/constraint pair representing the dynamic invocation of [selector]
/// on a receiver constrained by [constraint].
class SelectorMask {
  final Selector selector;
  final AbstractValue receiver;
  @override
  final int hashCode;

  SelectorMask(this.selector, this.receiver)
    : hashCode = Hashing.mixHashCodeBits(selector.hashCode, receiver.hashCode);

  String get name => selector.name;

  /// Check that the mask applies to the element. Skip checking the name since
  /// this is called from [FunctionSet.query] which implicitly checks the name
  /// via the Map lookups.
  bool _applies(MemberEntity element, AbstractValueDomain domain) {
    if (!selector.appliesStructural(element)) {
      return false;
    }
    return domain
        .isTargetingMember(receiver, element, selector.memberName)
        .isPotentiallyTrue;
  }

  bool needsNoSuchMethodHandling(AbstractValueDomain domain) {
    return domain
        .needsNoSuchMethodHandling(receiver, selector)
        .isPotentiallyTrue;
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    return other is SelectorMask &&
        selector == other.selector &&
        receiver == other.receiver;
  }

  @override
  String toString() => '($selector,$receiver)';
}

/// A node in the [FunctionSet] caching all [FunctionSetQuery] object for
/// selectors with the same [name].
class FunctionSetNode {
  final Map<SelectorMask, FunctionSetQuery> cache = {};

  // Initially, we keep the elements in a list because it is more
  // compact than a hash set. Once we get enough elements, we change
  // the representation to be a set to get faster contains checks.
  static const int maxElementsInList = 8;
  Iterable<MemberEntity> elements = [];
  bool isList = true;

  FunctionSetNode();

  void add(MemberEntity element) {
    // We try to avoid clearing the cache unless we have to. For that
    // reason we keep the explicit contains check even though the add
    // method ends up doing the work again (for sets).
    if (!elements.contains(element)) {
      if (isList && elements.length >= maxElementsInList) {
        elements = elements.toSet();
        isList = false;
      }
      if (isList) {
        final list = elements as List<MemberEntity>;
        list.add(element);
      } else {
        final set = elements as Set<MemberEntity>;
        set.add(element);
      }
      if (cache.isNotEmpty) cache.clear();
    }
  }

  void remove(MemberEntity element) {
    if (isList) {
      final list = elements as List<MemberEntity>;
      int index = list.indexOf(element);
      if (index < 0) return;
      MemberEntity last = list.removeLast();
      if (index != list.length) {
        list[index] = last;
      }
      if (cache.isNotEmpty) cache.clear();
    } else {
      final set = elements as List<MemberEntity>;
      if (set.remove(element)) {
        // To avoid wobbling between the two representations, we do
        // not transition back to the list representation even if we
        // end up with few enough elements at this point.
        if (cache.isNotEmpty) cache.clear();
      }
    }
  }

  bool contains(MemberEntity element) {
    return elements.contains(element);
  }

  void forEach(void Function(MemberEntity member) action) {
    elements.forEach(action);
  }

  /// Returns the set of functions that can be the target of [selectorMask]
  /// including no such method handling where applicable.
  FunctionSetQuery query(
    SelectorMask selectorMask,
    AbstractValueDomain domain, [
    FunctionSetNode? noSuchMethods,
    SelectorMask? noSuchMethodMask,
  ]) {
    FunctionSetQuery? result = cache[selectorMask];
    if (result != null) return result;

    Setlet<MemberEntity>? functions;
    for (MemberEntity element in elements) {
      if (selectorMask._applies(element, domain)) {
        // Defer the allocation of the functions set until we are
        // sure we need it. This allows us to return immutable empty
        // lists when the filtering produced no results.
        functions ??= Setlet();
        functions.add(element);
      }
    }

    // If we cannot ensure a method will be found at runtime, we also
    // add [noSuchMethod] implementations that apply to [mask] as
    // potential targets.
    if (noSuchMethods != null &&
        selectorMask.needsNoSuchMethodHandling(domain)) {
      // If [noSuchMethods] was provided then [noSuchMethodMask] should also
      // have been provided.
      FunctionSetQuery noSuchMethodQuery = noSuchMethods.query(
        noSuchMethodMask!,
        domain,
      );
      if (noSuchMethodQuery.functions.isNotEmpty) {
        functions ??= Setlet();
        functions.addAll(noSuchMethodQuery.functions);
      }
    }
    cache[selectorMask] = result = (functions != null)
        ? FullFunctionSetQuery(functions)
        : const EmptyFunctionSetQuery();
    return result;
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('FunctionSetNode(');
    String comma = '';
    cache.forEach((mask, query) {
      sb.write(comma);
      sb.write('$mask=$query');
      comma = ',';
    });
    sb.write(')');
    return sb.toString();
  }
}

/// A set of functions that are the potential targets of all call sites sharing
/// the same receiver mask and selector.
abstract class FunctionSetQuery {
  const FunctionSetQuery();

  /// Returns all potential targets of this function set.
  Iterable<MemberEntity> get functions;
}

class EmptyFunctionSetQuery implements FunctionSetQuery {
  const EmptyFunctionSetQuery();

  @override
  Iterable<MemberEntity> get functions => const [];

  @override
  String toString() => '<empty>';
}

class FullFunctionSetQuery implements FunctionSetQuery {
  @override
  final Iterable<MemberEntity> functions;

  FullFunctionSetQuery(this.functions);

  @override
  String toString() => 'FunctionSetQuery($functions)';
}
