// Copyright (c) 2024, 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:front_end/src/fasta/util/parser_ast.dart';
import 'package:front_end/src/fasta/util/parser_ast_helper.dart';

/// Visitor indexing methods/fields, both toplevel and in classes etc.
/// It does not recurse in to children of these, and doing so will potentially
/// ruin the handling of metadata.
class AstIndexer extends IgnoreSomeForCompatibilityAstVisitor {
  Map<String, int> nameIndex = {};
  List<int> positionStartEndIndex = [];
  List<ParserAstNode> positionNodeIndex = [];
  List<String> positionNodeName = [];
  String? currentContainerName;

  String? nameOfEntitySpanning(int position) {
    int? nodeIndex =
        moveNodeIndexPastMetadata(findNodeIndexSpanningPosition(position));
    if (nodeIndex != null) {
      return positionNodeName[nodeIndex];
    }
    return null;
  }

  int? moveNodeIndexToFirstMetadataIfAny(int? nodeIndex) {
    if (nodeIndex == null) return nodeIndex;

    while (nodeIndex! > 0 && positionNodeIndex[nodeIndex - 1] is MetadataEnd) {
      nodeIndex--;
    }
    return nodeIndex;
  }

  int? moveNodeIndexPastMetadata(int? nodeIndex) {
    if (nodeIndex == null) return nodeIndex;
    while (nodeIndex! < positionNodeIndex.length &&
        positionNodeIndex[nodeIndex] is MetadataEnd) {
      nodeIndex++;
    }
    if (nodeIndex < positionNodeIndex.length &&
        positionNodeIndex[nodeIndex] is! MetadataEnd) {
      return nodeIndex;
    }
    return null;
  }

  int? findNodeIndexSpanningPosition(int position) {
    int low = 0;
    int high = positionNodeIndex.length - 1;
    while (low < high) {
      int mid = high - ((high - low) >> 1); // Get middle, rounding up.
      int start1 = positionStartEndIndex[mid * 2 + 0];
      int end1 = positionStartEndIndex[mid * 2 + 1];

      if (position > end1) {
        // After the entity --- no matter if this is a container or not
        // we're after it.
        low = mid;
      } else if (position < start1) {
        // Before the entity --- no matter if this is a container or not
        // we're before it.
        high = mid - 1;
      } else {
        // Inside this entity --- if this entity is a container
        // (i.e. the next entity is also inside this entity) try to find
        // something more specific.
        if (mid + 1 < positionNodeIndex.length) {
          int start2 = positionStartEndIndex[(mid + 1) * 2 + 0];
          if (start2 < end1 /* i.e. inside */ && start2 <= position) {
            low = mid + 1;
            continue;
          }
        }

        return mid;
      }
    }
    int start = positionStartEndIndex[low * 2 + 0];
    int end = positionStartEndIndex[low * 2 + 1];
    if (position >= start && position <= end) {
      return low;
    }

    return null;
  }

  @override
  void visitClassDeclarationEnd(ClassDeclarationEnd node) {
    currentContainerName = node.getClassIdentifier().token.lexeme;
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    nameIndex[currentContainerName!] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(currentContainerName!);
    super.visitClassDeclarationEnd(node);
    currentContainerName = null;
  }

  @override
  void visitEnumEnd(EnumEnd node) {
    currentContainerName = node.getEnumIdentifier().token.lexeme;
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    nameIndex[currentContainerName!] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(currentContainerName!);
    super.visitEnumEnd(node);
    currentContainerName = null;
  }

  @override
  void visitExtensionDeclarationEnd(ExtensionDeclarationEnd node) {
    currentContainerName =
        node.getExtensionName()?.lexeme ?? "<unnamed extension>";
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    nameIndex[currentContainerName!] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(currentContainerName!);
    super.visitExtensionDeclarationEnd(node);
    currentContainerName = null;
  }

  @override
  void visitExtensionTypeDeclarationEnd(ExtensionTypeDeclarationEnd node) {
    currentContainerName =
        node.getExtensionTypeName()?.lexeme ?? "<unnamed extension type>";
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    nameIndex[currentContainerName!] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(currentContainerName!);
    super.visitExtensionTypeDeclarationEnd(node);
    currentContainerName = null;
  }

  @override
  void visitMixinDeclarationEnd(MixinDeclarationEnd node) {
    currentContainerName = node.getMixinIdentifier().token.lexeme;
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    nameIndex[currentContainerName!] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(currentContainerName!);
    super.visitMixinDeclarationEnd(node);
    currentContainerName = null;
  }

  @override
  void visitNamedMixinApplicationEnd(NamedMixinApplicationEnd node) {
    currentContainerName = node.getMixinIdentifier().token.lexeme;
    positionStartEndIndex.add(node.begin.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    nameIndex[currentContainerName!] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(currentContainerName!);
    super.visitNamedMixinApplicationEnd(node);
    currentContainerName = null;
  }

  @override
  void visitTopLevelMethodEnd(TopLevelMethodEnd node) {
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    // TODO(jensj): Setters.
    String name = node.getNameIdentifier().token.lexeme;
    nameIndex[name] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(name);
  }

  @override
  void visitTopLevelFieldsEnd(TopLevelFieldsEnd node) {
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    String? firstName;
    for (IdentifierHandle identifier in node.getFieldIdentifiers()) {
      String name = identifier.token.lexeme;
      firstName ??= name;
      nameIndex[name] = positionNodeIndex.length;
    }
    positionNodeIndex.add(node);
    positionNodeName.add(firstName!);
  }

  @override
  void visitMetadataStarEnd(MetadataStarEnd node) {
    for (MetadataEnd metadata in node.getMetadataEntries()) {
      positionStartEndIndex.add(metadata.beginToken.charOffset);
      positionStartEndIndex.add(metadata.endToken.charEnd);
      positionNodeIndex.add(metadata);
      positionNodeName.add("<metadata>");
    }
  }

  void containerMethod(
      BeginAndEndTokenParserAstNode node, String nameIdentifier) {
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    // TODO(jensj): Setters.
    String name = "$currentContainerName.$nameIdentifier";
    nameIndex[name] = positionNodeIndex.length;
    positionNodeIndex.add(node);
    positionNodeName.add(name);
  }

  void containerFields(
      BeginAndEndTokenParserAstNode node, List<IdentifierHandle> names) {
    positionStartEndIndex.add(node.beginToken.charOffset);
    positionStartEndIndex.add(node.endToken.charEnd);
    String? firstName;
    for (IdentifierHandle identifier in names) {
      String name = "$currentContainerName.${identifier.token.lexeme}";
      firstName ??= name;
      nameIndex[name] = positionNodeIndex.length;
    }
    positionNodeIndex.add(node);
    positionNodeName.add(firstName!);
  }

  @override
  void visitClassConstructorEnd(ClassConstructorEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitClassFactoryMethodEnd(ClassFactoryMethodEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitClassFieldsEnd(ClassFieldsEnd node) {
    containerFields(node, node.getFieldIdentifiers());
  }

  @override
  void visitClassMethodEnd(ClassMethodEnd node) {
    containerMethod(node, node.getNameIdentifier());
  }

  @override
  void visitMixinConstructorEnd(MixinConstructorEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitMixinFactoryMethodEnd(MixinFactoryMethodEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitMixinFieldsEnd(MixinFieldsEnd node) {
    containerFields(node, node.getFieldIdentifiers());
  }

  @override
  void visitMixinMethodEnd(MixinMethodEnd node) {
    containerMethod(node, node.getNameIdentifier());
  }

  @override
  void visitEnumConstructorEnd(EnumConstructorEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitEnumFactoryMethodEnd(EnumFactoryMethodEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitEnumFieldsEnd(EnumFieldsEnd node) {
    containerFields(node, node.getFieldIdentifiers());
  }

  @override
  void visitEnumMethodEnd(EnumMethodEnd node) {
    containerMethod(node, node.getNameIdentifier());
  }

  @override
  void visitExtensionConstructorEnd(ExtensionConstructorEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitExtensionFactoryMethodEnd(ExtensionFactoryMethodEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitExtensionFieldsEnd(ExtensionFieldsEnd node) {
    containerFields(node, node.getFieldIdentifiers());
  }

  @override
  void visitExtensionMethodEnd(ExtensionMethodEnd node) {
    containerMethod(node, node.getNameIdentifier());
  }

  @override
  void visitExtensionTypeConstructorEnd(ExtensionTypeConstructorEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitExtensionTypeFactoryMethodEnd(ExtensionTypeFactoryMethodEnd node) {
    containerMethod(node, node.getIdentifiers().last.token.lexeme);
  }

  @override
  void visitExtensionTypeFieldsEnd(ExtensionTypeFieldsEnd node) {
    containerFields(node, node.getFieldIdentifiers());
  }

  @override
  void visitExtensionTypeMethodEnd(ExtensionTypeMethodEnd node) {
    containerMethod(node, node.getNameIdentifier());
  }
}
