// Copyright (c) 2020, 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:kernel/ast.dart';

import 'utils.dart' show UnionFind;
import '../../metadata/procedure_attributes.dart';
import '../../metadata/table_selector.dart';

// Assigns dispatch table selector IDs to interface targets.
class TableSelectorAssigner {
  final TableSelectorMetadata metadata = TableSelectorMetadata();

  final Map<Class, Map<Name, int>> _getterMemberIds = {};
  final Map<Class, Map<Name, int>> _methodOrSetterMemberIds = {};

  final UnionFind _unionFind = UnionFind();
  late List<int?> _selectorIdForMemberId;

  TableSelectorAssigner(Component component) {
    for (Library library in component.libraries) {
      for (Class cls in library.classes) {
        _memberIdsForClass(cls, getter: false);
        _memberIdsForClass(cls, getter: true);
      }
    }
    _selectorIdForMemberId = List.filled(_unionFind.size, null);
    // Assign all selector IDs eagerly to make them independent of how they are
    // queried in later phases. This makes TFA test expectation files (which
    // contain selector IDs) more stable under changes to how selector IDs are
    // used in TFA phases.
    for (Library library in component.libraries) {
      for (Class cls in library.classes) {
        for (Member member in cls.members) {
          if (member.isInstanceMember) {
            _selectorIdForMember(member, getter: false);
            _selectorIdForMember(member, getter: true);
          }
        }
      }
    }
  }

  Map<Name, int> _memberIdsForClass(Class? cls, {required bool getter}) {
    if (cls == null) return {};

    final cache = getter ? _getterMemberIds : _methodOrSetterMemberIds;

    // Already computed for this class?
    final cachedMemberIds = cache[cls];
    if (cachedMemberIds != null) return cachedMemberIds;

    // Merge maps from supertypes.
    final memberIds =
        Map<Name, int>.from(_memberIdsForClass(cls.superclass, getter: getter));
    for (Supertype impl in cls.implementedTypes) {
      _memberIdsForClass(impl.classNode, getter: getter).forEach((name, id) {
        final int? firstId = memberIds[name];
        if (firstId == null) {
          memberIds[name] = id;
        } else if (firstId != id) {
          _unionFind.union(firstId, id);
        }
      });
    }

    // Add declared instance members.
    for (Member member in cls.members) {
      if (member.isInstanceMember) {
        bool addToMap;
        if (member is Procedure) {
          switch (member.kind) {
            case ProcedureKind.Method:
              addToMap = true;
              break;
            case ProcedureKind.Operator:
            case ProcedureKind.Setter:
              addToMap = !getter;
              break;
            case ProcedureKind.Getter:
              addToMap = getter;
              break;
            default:
              throw "Unexpected procedure kind '${member.kind}'";
          }
        } else if (member is Field) {
          addToMap = getter || member.hasSetter;
        } else {
          throw "Unexpected member kind '${member.runtimeType}'";
        }
        if (addToMap && !memberIds.containsKey(member.name)) {
          memberIds[member.name] = _unionFind.add();
        }
      }
    }

    return cache[cls] = memberIds;
  }

  int _selectorIdForMember(Member member, {required bool getter}) {
    final map = getter ? _getterMemberIds : _methodOrSetterMemberIds;
    int? memberId = map[member.enclosingClass!]![member.name];
    if (memberId == null) {
      assert(member is Procedure &&
              ((identical(map, _getterMemberIds) &&
                      (member.kind == ProcedureKind.Operator ||
                          member.kind == ProcedureKind.Setter)) ||
                  identical(map, _methodOrSetterMemberIds) &&
                      member.kind == ProcedureKind.Getter) ||
          member is Field &&
              identical(map, _methodOrSetterMemberIds) &&
              !member.hasSetter);
      return ProcedureAttributesMetadata.kInvalidSelectorId;
    }
    memberId = _unionFind.find(memberId);
    int? selectorId = _selectorIdForMemberId[memberId];
    if (selectorId == null) {
      _selectorIdForMemberId[memberId] = selectorId = metadata.addSelector();
    }
    return selectorId;
  }

  int methodOrSetterSelectorId(Member member) {
    return _selectorIdForMember(member, getter: false);
  }

  int getterSelectorId(Member member) {
    return _selectorIdForMember(member, getter: true);
  }

  void registerMethodOrSetterCall(Member member, bool calledOnNull) {
    final TableSelectorInfo selector =
        metadata.selectors[methodOrSetterSelectorId(member)];
    selector.callCount++;
    selector.calledOnNull |= calledOnNull;
  }

  void registerGetterCall(Member member, bool calledOnNull) {
    final TableSelectorInfo selector =
        metadata.selectors[getterSelectorId(member)];
    selector.callCount++;
    selector.calledOnNull |= calledOnNull;
    if (member is Procedure && member.kind == ProcedureKind.Method) {
      final TableSelectorInfo methodSelector =
          metadata.selectors[methodOrSetterSelectorId(member)];
      methodSelector.tornOff = true;
    }
  }

  /// A (conservative) number which is bigger than all selector IDs.
  int get selectorIdRange => metadata.selectors.length;
}
