// 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)}))';
}
