// 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:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:front_end/src/codes/diagnostic.dart' as diag;
import 'package:kernel/ast.dart';

import '../base/export.dart';
import '../base/identifiers.dart';
import '../base/import.dart';
import '../base/problems.dart';
import '../fragment/fragment.dart';

/// Map from offsets of directives and declarations to the objects the define.
///
/// This is used to connect parsing of the [OutlineBuilder], where the objects
/// are created, with the [DietListener], where the objects are looked up.
class OffsetMap {
  final Uri uri;
  final Map<int, DeclarationFragmentImpl> _declarations = {};
  final Map<int, FieldFragment> _fields = {};
  final Map<int, PrimaryConstructorFragment> _primaryConstructors = {};
  final Map<int, PrimaryConstructorBodyFragment> _primaryConstructorBodies = {};
  final Map<int, ConstructorFragment> _constructors = {};
  final Map<int, FactoryFragment> _factoryFragments = {};
  final Map<int, GetterFragment> _getters = {};
  final Map<int, SetterFragment> _setters = {};
  final Map<int, MethodFragment> _methods = {};
  final Map<int, LibraryPart> _parts = {};
  final Map<int, Import> _imports = {};
  final Map<int, Export> _exports = {};

  new(this.uri);

  void registerImport(Token importKeyword, Import import) {
    assert(
      importKeyword.lexeme == 'import',
      "Invalid token for import: $importKeyword.",
    );
    _imports[importKeyword.charOffset] = import;
  }

  Import lookupImport(Token importKeyword) {
    assert(
      importKeyword.lexeme == 'import',
      "Invalid token for import: $importKeyword.",
    );
    return _checkDirective(
      _imports[importKeyword.charOffset],
      '<import>',
      importKeyword.charOffset,
    );
  }

  void registerExport(Token exportKeyword, Export export) {
    assert(
      exportKeyword.lexeme == 'export',
      "Invalid token for export: $exportKeyword.",
    );
    _exports[exportKeyword.charOffset] = export;
  }

  Export lookupExport(Token exportKeyword) {
    assert(
      exportKeyword.lexeme == 'export',
      "Invalid token for export: $exportKeyword.",
    );
    return _checkDirective(
      _exports[exportKeyword.charOffset],
      '<export>',
      exportKeyword.charOffset,
    );
  }

  void registerPart(Token partKeyword, LibraryPart part) {
    assert(
      partKeyword.lexeme == 'part',
      "Invalid token for part: $partKeyword.",
    );
    _parts[partKeyword.charOffset] = part;
  }

  LibraryPart lookupPart(Token partKeyword) {
    assert(
      partKeyword.lexeme == 'part',
      "Invalid token for part: $partKeyword.",
    );
    return _checkDirective(
      _parts[partKeyword.charOffset],
      '<part>',
      partKeyword.charOffset,
    );
  }

  void registerNamedDeclarationFragment(
    Identifier identifier,
    DeclarationFragmentImpl fragment,
  ) {
    _declarations[identifier.nameOffset] = fragment;
  }

  DeclarationFragmentImpl lookupNamedDeclaration(Identifier identifier) {
    return _checkFragment(
      _declarations[identifier.nameOffset],
      identifier.name,
      identifier.nameOffset,
    );
  }

  void registerUnnamedDeclaration(
    Token beginToken,
    DeclarationFragmentImpl fragment,
  ) {
    _declarations[beginToken.charOffset] = fragment;
  }

  DeclarationFragmentImpl lookupUnnamedDeclaration(Token beginToken) {
    return _checkFragment(
      _declarations[beginToken.charOffset],
      '<unnamed-declaration>',
      beginToken.charOffset,
    );
  }

  void registerField(Identifier identifier, FieldFragment fragment) {
    _fields[identifier.nameOffset] = fragment;
  }

  FieldFragment lookupField(Identifier identifier) {
    return _checkFragment(
      _fields[identifier.nameOffset],
      identifier.name,
      identifier.nameOffset,
    );
  }

  void registerPrimaryConstructor(
    Token beginToken,
    PrimaryConstructorFragment fragment,
  ) {
    _primaryConstructors[beginToken.charOffset] = fragment;
  }

  FunctionFragment lookupPrimaryConstructor(Token beginToken) {
    return _checkFragment(
      _primaryConstructors[beginToken.charOffset],
      '<primary-constructor>',
      beginToken.charOffset,
    );
  }

  void registerPrimaryConstructorBody(
    Token token,
    PrimaryConstructorBodyFragment fragment,
  ) {
    _primaryConstructorBodies[token.charOffset] = fragment;
  }

  PrimaryConstructorBodyFragment lookupPrimaryConstructorBody(
    Token beginToken,
  ) {
    return _checkFragment(
      _primaryConstructorBodies[beginToken.charOffset],
      '<primary-constructor-body>',
      beginToken.charOffset,
    );
  }

  void registerConstructorFragment(
    Identifier identifier,
    ConstructorFragment fragment,
  ) {
    _constructors[identifier.nameOffset] = fragment;
  }

  void registerFactoryFragment(
    Identifier identifier,
    FactoryFragment fragment,
  ) {
    _factoryFragments[identifier.nameOffset] = fragment;
  }

  FunctionFragment lookupConstructor(Identifier identifier) {
    FunctionFragment? fragment = _constructors[identifier.nameOffset];
    fragment ??= _factoryFragments[identifier.nameOffset];
    return _checkFragment(fragment, identifier.name, identifier.nameOffset);
  }

  void registerGetter(Identifier identifier, GetterFragment fragment) {
    _getters[identifier.nameOffset] = fragment;
  }

  void registerSetter(Identifier identifier, SetterFragment fragment) {
    _setters[identifier.nameOffset] = fragment;
  }

  void registerMethod(Identifier identifier, MethodFragment fragment) {
    _methods[identifier.nameOffset] = fragment;
  }

  FunctionFragment lookupGetter(Identifier identifier) {
    return _checkFragment(
      _getters[identifier.nameOffset],
      identifier.name,
      identifier.nameOffset,
    );
  }

  FunctionFragment lookupSetter(Identifier identifier) {
    return _checkFragment(
      _setters[identifier.nameOffset],
      identifier.name,
      identifier.nameOffset,
    );
  }

  FunctionFragment lookupMethod(Identifier identifier) {
    return _checkFragment(
      _methods[identifier.nameOffset],
      identifier.name,
      identifier.nameOffset,
    );
  }

  T _checkDirective<T>(T? directive, String name, int charOffset) {
    if (directive == null) {
      internalProblem(
        diag.internalProblemNotFound.withArguments(name: name),
        charOffset,
        uri,
      );
    }
    return directive;
  }

  T _checkFragment<T>(T? fragment, String name, int fileOffset) {
    if (fragment == null) {
      internalProblem(
        diag.internalProblemNotFound.withArguments(name: name),
        fileOffset,
        uri,
      );
    }
    return fragment;
  }
}
