// 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:kernel/ast.dart' as ir;

import 'node_indexer.dart';

/// Helper for looking up object library data from an [ir.Component] node.
class ComponentLookup {
  final ir.Component _component;

  /// Cache of [LibraryData] for libraries in [_component].
  late final Map<Uri, LibraryData> _libraryMap = _initializeLibraryMap();

  ComponentLookup(this._component);

  Map<Uri, LibraryData> _initializeLibraryMap() {
    final libraryMap = <Uri, LibraryData>{};
    for (ir.Library library in _component.libraries) {
      libraryMap[library.importUri] = LibraryData(library);
    }
    return libraryMap;
  }

  /// Returns the [LibraryData] object for the library with the [canonicalUri].
  LibraryData getLibraryDataByUri(Uri canonicalUri) {
    return _libraryMap[canonicalUri]!;
  }
}

/// Returns a name uniquely identifying a member within its enclosing library
/// or class.
String computeMemberName(ir.Member member) {
  // This should mostly be empty except when serializing the name of nSM
  // forwarders (see dartbug.com/33732).
  String libraryPrefix = member.name.isPrivate &&
          member.name.libraryReference != member.enclosingLibrary.reference
      ? '${member.name.libraryReference?.canonicalName?.name}:'
      : '';
  String name = member.name.text;
  if (member is ir.Constructor) {
    name = '.$name';
  } else if (member is ir.Procedure) {
    if (member.kind == ir.ProcedureKind.Factory) {
      name = '.$name';
    } else if (member.kind == ir.ProcedureKind.Setter) {
      name += "=";
    }
  }
  return '${libraryPrefix}${name}';
}

/// Helper for looking up classes and members from an [ir.Library] node.
class LibraryData {
  /// The [ir.Library] that defines the library.
  final ir.Library node;

  /// Cache of [ClassData] for classes in this library.
  Map<String, ClassData>? _classesByName;
  Map<ir.Class, ClassData>? _classesByNode;

  /// Cache of [ir.Typedef] nodes for typedefs in this library.
  late final Map<String, ir.Typedef> _typedefs = _initializeTypedefs();

  /// Cache of [ir.ExtensionTypeDeclaration] nodes for extension type
  /// declarations in this library.
  late final Map<String, ir.ExtensionTypeDeclaration>
      _extensionTypeDeclarations = _initializeExtensionTypeDeclarations();

  /// Cache of [MemberData] for members in this library.
  Map<String, MemberData>? _membersByName;
  Map<ir.Member, MemberData>? _membersByNode;

  LibraryData(this.node);

  Map<String, ir.Typedef> _initializeTypedefs() {
    final typedefs = <String, ir.Typedef>{};
    for (ir.Typedef typedef in node.typedefs) {
      assert(
          !typedefs.containsKey(typedef.name),
          "Duplicate typedef '${typedef.name}' in $typedefs "
          "trying to add $typedef.");
      typedefs[typedef.name] = typedef;
    }
    return typedefs;
  }

  Map<String, ir.ExtensionTypeDeclaration>
      _initializeExtensionTypeDeclarations() {
    final extensionTypeDeclarations = <String, ir.ExtensionTypeDeclaration>{};
    for (ir.ExtensionTypeDeclaration extensionTypeDeclaration
        in node.extensionTypeDeclarations) {
      assert(
          !extensionTypeDeclarations.containsKey(extensionTypeDeclaration.name),
          "Duplicate extension type declaration "
          "'${extensionTypeDeclaration.name}' in  $extensionTypeDeclarations "
          "trying to add $extensionTypeDeclaration.");
      extensionTypeDeclarations[extensionTypeDeclaration.name] =
          extensionTypeDeclaration;
    }
    return extensionTypeDeclarations;
  }

  void _ensureClasses() {
    if (_classesByName == null) {
      final classesByName = _classesByName = {};
      final classesByNode = _classesByNode = {};
      for (ir.Class cls in node.classes) {
        assert(
            !classesByName.containsKey(cls.name),
            "Duplicate class '${cls.name}' in $classesByName "
            "trying to add $cls.");
        assert(
            !classesByNode.containsKey(cls),
            "Duplicate class '${cls.name}' in $classesByNode "
            "trying to add $cls.");
        classesByNode[cls] = classesByName[cls.name] = ClassData(cls);
      }
    }
  }

  /// Returns the [ClassData] for the class [name] in this library.
  ClassData? lookupClassByName(String name) {
    _ensureClasses();
    return _classesByName![name];
  }

  /// Returns the [ClassData] for the class [node] in this library.
  ClassData? lookupClassByNode(ir.Class node) {
    _ensureClasses();
    return _classesByNode![node];
  }

  /// Returns the [ExtensionTypeDeclaration] for the given [name] in this
  /// library.
  ir.ExtensionTypeDeclaration? lookupExtensionTypeDeclaration(String name) {
    return _extensionTypeDeclarations[name];
  }

  ir.Typedef? lookupTypedef(String name) {
    return _typedefs[name];
  }

  void _ensureMembers() {
    if (_membersByName == null) {
      final membersByName = _membersByName = {};
      final membersByNode = _membersByNode = {};
      for (ir.Member member in node.members) {
        String name = computeMemberName(member);
        assert(
            !membersByName.containsKey(name),
            "Duplicate member '$name' in $membersByName "
            "trying to add $member.");
        assert(
            !membersByNode.containsKey(member),
            "Duplicate member '$name' in $membersByNode "
            "trying to add $member.");
        membersByNode[member] = membersByName[name] = MemberData(member);
      }
    }
  }

  /// Returns the [MemberData] for the member uniquely identified by [name] in
  /// this library.
  MemberData? lookupMemberDataByName(String name) {
    _ensureMembers();
    return _membersByName![name];
  }

  /// Returns the [MemberData] for the member [node] in this library.
  MemberData? lookupMemberDataByNode(ir.Member node) {
    _ensureMembers();
    return _membersByNode![node];
  }

  @override
  String toString() => 'LibraryData($node(${identityHashCode(node)}))';
}

/// Helper for looking up members from an [ir.Class] node.
class ClassData {
  /// The [ir.Class] that defines the class.
  final ir.Class node;

  /// Cache of [MemberData] for members in this class.
  Map<String, MemberData>? _membersByName;
  Map<ir.Member, MemberData>? _membersByNode;

  ClassData(this.node);

  void _ensureMembers() {
    if (_membersByName == null) {
      final membersByName = _membersByName = {};
      final membersByNode = _membersByNode = {};
      for (ir.Member member in node.members) {
        String name = computeMemberName(member);
        assert(
            !membersByName.containsKey(name),
            "Duplicate member '$name' in $membersByName "
            "trying to add $member.");
        assert(
            !membersByNode.containsKey(member),
            "Duplicate member '$name' in $membersByNode "
            "trying to add $member.");
        membersByNode[member] = membersByName[name] = MemberData(member);
      }
    }
  }

  /// Returns the [MemberData] for the member uniquely identified by [name] in
  /// this class.
  MemberData? lookupMemberDataByName(String name) {
    _ensureMembers();
    return _membersByName![name];
  }

  /// Returns the [MemberData] for the member [node] in this class.
  MemberData? lookupMemberDataByNode(ir.Member node) {
    _ensureMembers();
    return _membersByNode![node];
  }

  @override
  String toString() => 'ClassData($node(${identityHashCode(node)}))';
}

/// Helper for looking up child [ir.TreeNode]s of a [ir.Member] node.
class MemberData {
  /// The [ir.Member] that defines the member.
  final ir.Member node;

  /// Cached index to [ir.TreeNode] map used for deserialization of
  /// [ir.TreeNode]s.
  Map<int, ir.TreeNode>? _indexToNodeMap;

  /// Cached [ir.TreeNode] to index map used for serialization of
  /// [ir.TreeNode]s.
  Map<ir.TreeNode, int>? _nodeToIndexMap;

  /// Cached [ir.ConstantExpression] to [ConstantNodeIndexerVisitor] map used
  /// for fast serialization/deserialization of constant references.
  late final Map<ir.ConstantExpression, ConstantNodeIndexerVisitor>
      _constantIndexMap = {};

  MemberData(this.node);

  void _ensureMaps() {
    if (_indexToNodeMap == null) {
      _indexToNodeMap = {};
      _nodeToIndexMap = {};
      node.accept(TreeNodeIndexerVisitor(_indexToNodeMap!, _nodeToIndexMap!));
    }
  }

  ConstantNodeIndexerVisitor _createConstantIndexer(
      ir.ConstantExpression node) {
    ConstantNodeIndexerVisitor indexer = ConstantNodeIndexerVisitor();
    node.constant.accept(indexer);
    return indexer;
  }

  ir.Constant getConstantByIndex(ir.ConstantExpression node, int index) {
    ConstantNodeIndexerVisitor indexer =
        _constantIndexMap[node] ??= _createConstantIndexer(node);
    return indexer.getConstant(index);
  }

  int getIndexByConstant(ir.ConstantExpression node, ir.Constant constant) {
    ConstantNodeIndexerVisitor indexer =
        _constantIndexMap[node] ??= _createConstantIndexer(node);
    return indexer.getIndex(constant);
  }

  /// Returns the [ir.TreeNode] corresponding to [index] in this member.
  ir.TreeNode getTreeNodeByIndex(int index) {
    _ensureMaps();
    return _indexToNodeMap![index]!;
  }

  /// Returns the index corresponding to [ir.TreeNode] in this member.
  int getIndexByTreeNode(ir.TreeNode node) {
    _ensureMaps();
    return _nodeToIndexMap![node] ??
        (throw StateError(
            'getIndexByTreeNode ${node.runtimeType} in member ${this.node}'));
  }

  @override
  String toString() => 'MemberData($node(${identityHashCode(node)}))';
}
