// Copyright (c) 2025, 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.

part of 'fragment.dart';

class EnumElementFragment implements Fragment {
  final List<MetadataBuilder>? metadata;

  @override
  final String name;
  final int nameOffset;
  final Uri fileUri;

  final ConstructorReferenceBuilder? constructorReferenceBuilder;

  final LookupScope enclosingScope;
  final DeclarationFragment enclosingDeclaration;
  final LibraryFragment enclosingCompilationUnit;

  Token? _argumentsBeginToken;

  SourcePropertyBuilder? _builder;

  EnumElementDeclaration? _declaration;

  final TypeBuilder type = new InferableTypeBuilder();

  EnumElementFragment({
    required this.metadata,
    required this.name,
    required this.nameOffset,
    required this.fileUri,
    required this.constructorReferenceBuilder,
    required Token? argumentsBeginToken,
    required this.enclosingScope,
    required this.enclosingDeclaration,
    required this.enclosingCompilationUnit,
  }) : _argumentsBeginToken = argumentsBeginToken;

  @override
  SourcePropertyBuilder get builder {
    assert(_builder != null, "Builder has not been computed for $this.");
    return _builder!;
  }

  void set builder(SourcePropertyBuilder value) {
    assert(_builder == null, "Builder has already been computed for $this.");
    _builder = value;
  }

  EnumElementDeclaration get declaration {
    assert(
        _declaration != null, "Declaration has not been computed for $this.");
    return _declaration!;
  }

  void set declaration(EnumElementDeclaration value) {
    assert(_declaration == null,
        "Declaration has already been computed for $this.");
    _declaration = value;
  }

  UriOffsetLength get uriOffset =>
      new UriOffsetLength(fileUri, nameOffset, name.length);

  /// Returns the token for begin of the constructor arguments of this enum
  /// element, if any.
  ///
  /// This can only be called once and will hand over the responsibility of
  /// the token to the caller.
  Token? get argumentsBeginToken {
    Token? token = _argumentsBeginToken;
    _argumentsBeginToken = null;
    return token;
  }

  @override
  String toString() => '$runtimeType($name,$fileUri,$nameOffset)';
}

class _EnumElementClassMember implements ClassMember {
  final SourcePropertyBuilder _builder;
  final EnumElementFragment _fragment;

  Covariance? _covariance;

  _EnumElementClassMember(this._builder, this._fragment);

  @override
  bool get forSetter => false;

  @override
  UriOffsetLength get uriOffset => _fragment.uriOffset;

  @override
  DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;

  @override
  // Coverage-ignore(suite): Not run.
  List<ClassMember> get declarations =>
      throw new UnsupportedError('$runtimeType.declarations');

  @override
  // Coverage-ignore(suite): Not run.
  String get fullName {
    String className = declarationBuilder.fullNameForErrors;
    return "${className}.${fullNameForErrors}";
  }

  @override
  // Coverage-ignore(suite): Not run.
  String get fullNameForErrors => _builder.fullNameForErrors;

  @override
  // Coverage-ignore(suite): Not run.
  Covariance getCovariance(ClassMembersBuilder membersBuilder) {
    return _covariance ??= forSetter
        ? new Covariance.fromMember(getMember(membersBuilder),
            forSetter: forSetter)
        : const Covariance.empty();
  }

  @override
  Member getMember(ClassMembersBuilder membersBuilder) {
    inferType(membersBuilder);
    return forSetter
        ?
        // Coverage-ignore(suite): Not run.
        _builder.writeTarget!
        : _builder.readTarget!;
  }

  @override
  // Coverage-ignore(suite): Not run.
  MemberResult getMemberResult(ClassMembersBuilder membersBuilder) {
    return new StaticMemberResult(getMember(membersBuilder), memberKind,
        isDeclaredAsField: true,
        fullName: '${declarationBuilder.name}.${_builder.memberName.text}');
  }

  @override
  // Coverage-ignore(suite): Not run.
  Member? getTearOff(ClassMembersBuilder membersBuilder) => null;

  @override
  bool get hasDeclarations => false;

  @override
  void inferType(ClassMembersBuilder membersBuilder) {
    _builder.inferFieldType(membersBuilder.hierarchyBuilder);
  }

  @override
  ClassMember get interfaceMember => this;

  @override
  bool get isAbstract => false;

  @override
  bool get isDuplicate => _builder.isDuplicate;

  @override
  // Coverage-ignore(suite): Not run.
  bool get isExtensionTypeMember => _builder.isExtensionTypeMember;

  @override
  // Coverage-ignore(suite): Not run.
  bool get isNoSuchMethodForwarder => false;

  @override
  // Coverage-ignore(suite): Not run.
  bool isObjectMember(ClassBuilder objectClass) {
    return declarationBuilder == objectClass;
  }

  @override
  bool get isProperty => true;

  @override
  bool isSameDeclaration(ClassMember other) {
    return other is _EnumElementClassMember &&
        // Coverage-ignore(suite): Not run.
        _builder == other._builder;
  }

  @override
  // Coverage-ignore(suite): Not run.
  bool get isSetter => false;

  @override
  // Coverage-ignore(suite): Not run.
  bool get isSourceDeclaration => true;

  @override
  bool get isStatic => true;

  @override
  bool get isSynthesized => false;

  @override
  // Coverage-ignore(suite): Not run.
  ClassMemberKind get memberKind => ClassMemberKind.Getter;

  @override
  Name get name => _builder.memberName;

  @override
  // Coverage-ignore(suite): Not run.
  void registerOverrideDependency(
      ClassMembersBuilder membersBuilder, Set<ClassMember> overriddenMembers) {
    _builder.registerGetterOverrideDependency(
        membersBuilder, overriddenMembers);
  }

  @override
  String toString() => '$runtimeType($fullName)';
}

class _EnumElementFragmentBodyBuilderContext extends BodyBuilderContext {
  final EnumElementFragment _fragment;

  _EnumElementFragmentBodyBuilderContext(
      this._fragment,
      SourceLibraryBuilder libraryBuilder,
      DeclarationBuilder? declarationBuilder,
      {required bool isDeclarationInstanceMember})
      : super(libraryBuilder, declarationBuilder,
            isDeclarationInstanceMember: isDeclarationInstanceMember);

  @override
  // Coverage-ignore(suite): Not run.
  LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
    /// Initializer formals or super parameters cannot occur in getters so
    /// we don't need to create a new scope.
    return parent;
  }

  @override
  // Coverage-ignore(suite): Not run.
  int get memberNameOffset => _fragment.nameOffset;

  @override
  // Coverage-ignore(suite): Not run.
  int get memberNameLength => _fragment.name.length;

  @override
  // Coverage-ignore(suite): Not run.
  ConstantContext get constantContext {
    return ConstantContext.inferred;
  }
}

class EnumElementDeclaration
    with FieldDeclarationMixin
    implements
        FieldDeclaration,
        GetterDeclaration,
        Inferable,
        InferredTypeListener {
  final EnumElementFragment _fragment;

  Field? _field;

  late DartType _type = new InferredType(
      libraryBuilder: builder.libraryBuilder,
      typeBuilder: type,
      inferType: inferType,
      computeType: _computeType,
      fileUri: fileUri,
      name: _fragment.name,
      nameOffset: nameOffset,
      nameLength: _fragment.name.length,
      token: _fragment.argumentsBeginToken);

  late final int elementIndex;

  EnumElementDeclaration(this._fragment) {
    _fragment.declaration = this;
    type.registerInferable(this);
    type.registerInferredTypeListener(this);
  }

  @override
  void createFieldEncoding(SourcePropertyBuilder builder) {
    _fragment.builder = builder;
  }

  @override
  // Coverage-ignore(suite): Not run.
  UriOffsetLength get uriOffset => _fragment.uriOffset;

  DartType _computeType(ClassHierarchyBase hierarchy, Token? token) {
    SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
    SourceEnumBuilder sourceEnumBuilder =
        builder.declarationBuilder as SourceEnumBuilder;
    _buildElement(
        sourceEnumBuilder,
        sourceEnumBuilder.selfType.build(libraryBuilder, TypeUse.enumSelfType),
        libraryBuilder.loader.coreTypes,
        token);
    return fieldType;
  }

  @override
  bool get isEnumElement => true;

  @override
  Initializer buildErroneousInitializer(Expression effect, Expression value,
      {required int fileOffset}) {
    throw new UnsupportedError("${runtimeType}.buildErroneousInitializer");
  }

  @override
  void buildImplicitDefaultValue() {
    throw new UnsupportedError("${runtimeType}.buildImplicitDefaultValue");
  }

  @override
  Initializer buildImplicitInitializer() {
    throw new UnsupportedError("${runtimeType}.buildImplicitInitializer");
  }

  @override
  List<Initializer> buildInitializer(int fileOffset, Expression value,
      {required bool isSynthetic}) {
    throw new UnsupportedError("${runtimeType}.buildInitializer");
  }

  @override
  void buildFieldOutlineExpressions(
      {required ClassHierarchy classHierarchy,
      required SourceLibraryBuilder libraryBuilder,
      required DeclarationBuilder? declarationBuilder,
      required List<Annotatable> annotatables,
      required Uri annotatablesFileUri,
      required bool isClassInstanceMember}) {
    BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
    for (Annotatable annotatable in annotatables) {
      buildMetadataForOutlineExpressions(
          libraryBuilder: libraryBuilder,
          scope: _fragment.enclosingScope,
          bodyBuilderContext: bodyBuilderContext,
          annotatable: annotatable,
          annotatableFileUri: annotatablesFileUri,
          metadata: metadata);
    }
  }

  BodyBuilderContext createBodyBuilderContext() {
    return new _EnumElementFragmentBodyBuilderContext(
        _fragment, builder.libraryBuilder, builder.declarationBuilder,
        isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
  }

  @override
  void buildFieldOutlineNode(
      SourceLibraryBuilder libraryBuilder,
      NameScheme nameScheme,
      BuildNodesCallback f,
      PropertyReferences references,
      {required List<TypeParameter>? classTypeParameters}) {
    _field = new Field.immutable(dummyName,
        type: _type,
        isFinal: false,
        isConst: true,
        isStatic: true,
        fileUri: fileUri,
        fieldReference: references.fieldReference,
        getterReference: references.getterReference,
        isEnumElement: true)
      ..fileOffset = nameOffset
      ..fileEndOffset = nameOffset;
    nameScheme
        .getFieldMemberName(FieldNameType.Field, _fragment.name,
            isSynthesized: false)
        .attachMember(_field!);
    f(member: _field!, kind: BuiltMemberKind.Field);
  }

  void _buildElement(SourceEnumBuilder sourceEnumBuilder, DartType selfType,
      CoreTypes coreTypes, Token? token) {
    SourceLibraryBuilder libraryBuilder = sourceEnumBuilder.libraryBuilder;
    DartType inferredFieldType = selfType;

    String constant = _fragment.name;
    String constructorName =
        _fragment.constructorReferenceBuilder?.suffix ?? "";
    String fullConstructorNameForErrors =
        _fragment.constructorReferenceBuilder?.fullNameForErrors ??
            _fragment.name;
    int fileOffset =
        _fragment.constructorReferenceBuilder?.charOffset ?? nameOffset;
    constructorName = constructorName == "new" ? "" : constructorName;
    MemberBuilder? constructorBuilder =
        sourceEnumBuilder.nameSpace.lookupConstructor(constructorName);
    // TODO(CFE Team): Should there be a conversion to an invalid expression
    // instead? That's what happens on classes.
    while (constructorBuilder?.next != null) {
      constructorBuilder = constructorBuilder?.next as MemberBuilder;
    }

    ArgumentsImpl arguments;
    List<Expression> enumSyntheticArguments = <Expression>[
      new IntLiteral(elementIndex),
      new StringLiteral(constant),
    ];
    List<DartType>? typeArguments;
    List<TypeBuilder>? typeArgumentBuilders =
        _fragment.constructorReferenceBuilder?.typeArguments;
    if (typeArgumentBuilders != null) {
      typeArguments = <DartType>[];
      for (TypeBuilder typeBuilder in typeArgumentBuilders) {
        typeArguments.add(
            typeBuilder.build(libraryBuilder, TypeUse.constructorTypeArgument));
      }
    }
    if (libraryBuilder.libraryFeatures.enhancedEnums.isEnabled) {
      // We need to create a BodyBuilder to solve the following: 1) if
      // the arguments token is provided, we'll use the BodyBuilder to
      // parse them and perform inference, 2) if the type arguments
      // aren't provided, but required, we'll use it to infer them, and
      // 3) in case of erroneous code the constructor invocation should
      // be built via a body builder to detect potential errors.
      BodyBuilder bodyBuilder = libraryBuilder.loader
          .createBodyBuilderForOutlineExpression(
              libraryBuilder,
              sourceEnumBuilder.createBodyBuilderContext(),
              _fragment.enclosingScope,
              fileUri);
      bodyBuilder.constantContext = ConstantContext.inferred;

      if (token != null) {
        arguments = bodyBuilder.parseArguments(token);
        // We pass `true` for [allowFurtherDelays] here because the members of
        // the enums are built before the inference, and the resolution of the
        // redirecting factories can't be completed at this moment and
        // therefore should be delayed to another invocation of
        // [BodyBuilder.performBacklogComputations].
        bodyBuilder.performBacklogComputations();

        arguments.positional.insertAll(0, enumSyntheticArguments);
        arguments.argumentsOriginalOrder?.insertAll(0, enumSyntheticArguments);
      } else {
        arguments = new ArgumentsImpl(enumSyntheticArguments);
      }
      if (typeArguments != null) {
        ArgumentsImpl.setNonInferrableArgumentTypes(arguments, typeArguments);
      } else if (sourceEnumBuilder.cls.typeParameters.isNotEmpty) {
        arguments.types.addAll(new List<DartType>.filled(
            sourceEnumBuilder.cls.typeParameters.length, const UnknownType()));
      }
      setParents(enumSyntheticArguments, arguments);
      if (constructorBuilder == null ||
          constructorBuilder is! SourceConstructorBuilder) {
        assert(
            _field!.initializer == null,
            "Initializer has already been computed for $this: "
            "${_field!.initializer}.");
        _field!.initializer = bodyBuilder.buildUnresolvedError(
            fullConstructorNameForErrors, fileOffset,
            arguments: arguments, kind: UnresolvedKind.Constructor)
          ..parent = _field;
      } else {
        Expression initializer = bodyBuilder.buildStaticInvocation(
            constructorBuilder.invokeTarget, arguments,
            constness: Constness.explicitConst,
            charOffset: nameOffset,
            isConstructorInvocation: true);
        ExpressionInferenceResult inferenceResult = bodyBuilder.typeInferrer
            .inferFieldInitializer(
                bodyBuilder, const UnknownType(), initializer);
        initializer = inferenceResult.expression;
        inferredFieldType = inferenceResult.inferredType;
        assert(
            _field!.initializer == null,
            "Initializer has already been computed for $this: "
            "${_field!.initializer}.");
        _field!.initializer = initializer..parent = _field;
      }
    } else {
      arguments = new ArgumentsImpl(enumSyntheticArguments);
      setParents(enumSyntheticArguments, arguments);
      if (constructorBuilder == null ||
          constructorBuilder is! SourceConstructorBuilder ||
          !constructorBuilder.isConst) {
        // This can only occur if there enhanced enum features are used
        // when they are not enabled.
        assert(libraryBuilder.loader.hasSeenError);
        String text = libraryBuilder.loader.target.context
            .format(
                templateConstructorNotFound
                    .withArguments(fullConstructorNameForErrors)
                    .withLocation(fileUri, fileOffset, noLength),
                Severity.error)
            .plain;
        assert(
            _field!.initializer == null,
            "Initializer has already been computed for $this: "
            "${_field!.initializer}.");
        _field!.initializer = new InvalidExpression(text)
          ..fileOffset = nameOffset
          ..parent = _field;
      } else {
        Expression initializer = new ConstructorInvocation(
            constructorBuilder.invokeTarget as Constructor, arguments,
            isConst: true)
          ..fileOffset = nameOffset;
        assert(
            _field!.initializer == null,
            "Initializer has already been computed for $this: "
            "${_field!.initializer}.");
        _field!.initializer = initializer..parent = _field;
      }
    }
    fieldType = inferredFieldType;
  }

  @override
  void checkFieldTypes(SourceLibraryBuilder libraryBuilder,
      TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {}

  @override
  // Coverage-ignore(suite): Not run.
  void checkFieldVariance(
      SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {}

  @override
  int computeFieldDefaultTypes(ComputeDefaultTypeContext context) {
    return 0;
  }

  @override
  // Coverage-ignore(suite): Not run.
  void ensureTypes(
      ClassMembersBuilder membersBuilder,
      Set<ClassMember>? getterOverrideDependencies,
      Set<ClassMember>? setterOverrideDependencies) {
    inferType(membersBuilder.hierarchyBuilder);
  }

  @override
  bool get hasInitializer => true;

  @override
  bool get hasSetter => false;

  @override
  // Coverage-ignore(suite): Not run.
  shared.Expression? get initializerExpression =>
      throw new UnsupportedError('${runtimeType}.initializerExpression');

  @override
  // Coverage-ignore(suite): Not run.
  bool get isExtensionTypeDeclaredInstanceField => false;

  @override
  bool get isFinal => false;

  @override
  bool get isLate => false;

  @override
  List<ClassMember> get localMembers =>
      [new _EnumElementClassMember(builder, _fragment)];

  @override
  Member get readTarget => _field!;

  @override
  // Coverage-ignore(suite): Not run.
  DartType get fieldTypeInternal => _type;

  @override
  bool get isConst => true;

  @override
  // Coverage-ignore(suite): Not run.
  void setCovariantByClassInternal() {
    _field!.isCovariantByClass = true;
  }

  @override
  void set fieldTypeInternal(DartType value) {
    _type = value;
    _field?.type = value;
  }

  @override
  DartType get fieldType => _type;

  @override
  SourcePropertyBuilder get builder => _fragment.builder;

  @override
  Uri get fileUri => _fragment.fileUri;

  @override
  List<MetadataBuilder>? get metadata => _fragment.metadata;

  @override
  int get nameOffset => _fragment.nameOffset;

  @override
  TypeBuilder get type => _fragment.type;

  @override
  FieldQuality get fieldQuality => FieldQuality.Concrete;

  @override
  GetterQuality get getterQuality => GetterQuality.Implicit;

  @override
  void buildGetterOutlineExpressions(
      {required ClassHierarchy classHierarchy,
      required SourceLibraryBuilder libraryBuilder,
      required DeclarationBuilder? declarationBuilder,
      required SourcePropertyBuilder propertyBuilder,
      required Annotatable annotatable,
      required Uri annotatableFileUri,
      required bool isClassInstanceMember}) {}

  @override
  void buildGetterOutlineNode(
      {required SourceLibraryBuilder libraryBuilder,
      required NameScheme nameScheme,
      required BuildNodesCallback f,
      required PropertyReferences? references,
      required List<TypeParameter>? classTypeParameters}) {}

  @override
  void checkGetterTypes(SourceLibraryBuilder libraryBuilder,
      TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {}

  @override
  // Coverage-ignore(suite): Not run.
  void checkGetterVariance(
      SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {}

  @override
  int computeGetterDefaultTypes(ComputeDefaultTypeContext context) {
    return 0;
  }

  @override
  void createGetterEncoding(
      ProblemReporting problemReporting,
      SourcePropertyBuilder builder,
      PropertyEncodingStrategy encodingStrategy,
      List<NominalParameterBuilder> unboundNominalParameters) {}

  @override
  // Coverage-ignore(suite): Not run.
  void ensureGetterTypes(
      {required SourceLibraryBuilder libraryBuilder,
      required DeclarationBuilder? declarationBuilder,
      required ClassMembersBuilder membersBuilder,
      required Set<ClassMember>? getterOverrideDependencies}) {}

  @override
  // Coverage-ignore(suite): Not run.
  Iterable<Reference> getExportedGetterReferences(
      PropertyReferences references) {
    return [references.getterReference!];
  }
}
