// 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.

import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/type_environment.dart';

import '../../base/local_scope.dart';
import '../../base/scope.dart';
import '../../builder/declaration_builders.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/omitted_type_builder.dart';
import '../../builder/type_builder.dart';
import '../../builder/variable_builder.dart';
import '../../kernel/body_builder_context.dart';
import '../../kernel/internal_ast.dart';
import '../../kernel/type_algorithms.dart';
import '../../source/name_scheme.dart';
import '../../source/source_class_builder.dart';
import '../../source/source_function_builder.dart';
import '../../source/source_library_builder.dart';
import '../../source/source_loader.dart';
import '../../source/source_member_builder.dart';
import '../../source/source_property_builder.dart';
import '../../source/source_type_parameter_builder.dart';
import '../../source/type_parameter_factory.dart';
import '../fragment.dart';

class ExtensionInstanceSetterEncoding extends SetterEncoding
    with _ExtensionInstanceSetterEncodingMixin {
  @override
  final SetterFragment _fragment;

  @override
  final List<SourceNominalParameterBuilder>? _clonedDeclarationTypeParameters;

  @override
  final FormalParameterBuilder _thisFormal;

  ExtensionInstanceSetterEncoding(
    this._fragment,
    this._clonedDeclarationTypeParameters,
    this._thisFormal,
  );

  @override
  BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionSetter;

  @override
  bool get _isExtensionMember => true;

  @override
  bool get _isExtensionTypeMember => false;
}

class ExtensionStaticSetterEncoding extends SetterEncoding
    with _DirectSetterEncodingMixin {
  @override
  final SetterFragment _fragment;

  ExtensionStaticSetterEncoding(this._fragment);

  @override
  BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionSetter;

  @override
  bool get _isExtensionMember => true;

  @override
  bool get _isExtensionTypeMember => false;
}

class ExtensionTypeInstanceSetterEncoding extends SetterEncoding
    with _ExtensionInstanceSetterEncodingMixin {
  @override
  final SetterFragment _fragment;

  @override
  final List<SourceNominalParameterBuilder>? _clonedDeclarationTypeParameters;

  @override
  final FormalParameterBuilder _thisFormal;

  ExtensionTypeInstanceSetterEncoding(
    this._fragment,
    this._clonedDeclarationTypeParameters,
    this._thisFormal,
  );

  @override
  BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeSetter;

  @override
  bool get _isExtensionMember => false;

  @override
  bool get _isExtensionTypeMember => true;
}

class ExtensionTypeStaticSetterEncoding extends SetterEncoding
    with _DirectSetterEncodingMixin {
  @override
  final SetterFragment _fragment;

  ExtensionTypeStaticSetterEncoding(this._fragment);

  @override
  BuiltMemberKind get _builtMemberKind => BuiltMemberKind.ExtensionTypeSetter;

  @override
  bool get _isExtensionMember => false;

  @override
  bool get _isExtensionTypeMember => true;
}

class RegularSetterEncoding extends SetterEncoding
    with _DirectSetterEncodingMixin {
  @override
  final SetterFragment _fragment;

  RegularSetterEncoding(this._fragment);

  @override
  BuiltMemberKind get _builtMemberKind => BuiltMemberKind.Method;

  @override
  bool get _isExtensionMember => false;

  @override
  bool get _isExtensionTypeMember => false;
}

sealed class SetterEncoding {
  List<SourceNominalParameterBuilder>? get clonedAndDeclaredTypeParameters;
  List<FormalParameterBuilder>? get formals;
  FunctionNode get function;

  List<TypeParameter>? get thisTypeParameters;

  VariableDeclaration? get thisVariable;

  Procedure get writeTarget;

  void becomeNative(SourceLoader loader);

  void buildOutlineExpressions({
    required ClassHierarchy classHierarchy,
    required SourceLibraryBuilder libraryBuilder,
    required DeclarationBuilder? declarationBuilder,
    required BodyBuilderContext bodyBuilderContext,
    required Annotatable annotatable,
    required Uri annotatableFileUri,
    required bool isClassInstanceMember,
  });

  void buildOutlineNode({
    required SourceLibraryBuilder libraryBuilder,
    required NameScheme nameScheme,
    required BuildNodesCallback f,
    required PropertyReferences? references,
    required bool isAbstractOrExternal,
    required List<TypeParameter>? classTypeParameters,
  });

  void checkTypes(
    SourceLibraryBuilder libraryBuilder,
    TypeEnvironment typeEnvironment, {
    required bool isAbstract,
    required bool isExternal,
  });

  void checkVariance(
    SourceClassBuilder sourceClassBuilder,
    TypeEnvironment typeEnvironment,
  );

  int computeDefaultTypes(ComputeDefaultTypeContext context);

  LocalScope createFormalParameterScope(LookupScope typeParameterScope);

  void ensureTypes(
    SourceLibraryBuilder libraryBuilder,
    ClassHierarchyBase hierarchy,
  );

  VariableDeclaration getFormalParameter(int index);
}

mixin _DirectSetterEncodingMixin implements SetterEncoding {
  Procedure? _procedure;

  @override
  List<SourceNominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders;

  @override
  List<FormalParameterBuilder>? get formals => _fragment.declaredFormals;

  @override
  FunctionNode get function => _procedure!.function;

  @override
  List<TypeParameter>? get thisTypeParameters => null;

  @override
  VariableDeclaration? get thisVariable => null;

  @override
  Procedure get writeTarget => _procedure!;

  BuiltMemberKind get _builtMemberKind;

  SetterFragment get _fragment;

  bool get _isExtensionMember;

  bool get _isExtensionTypeMember;

  @override
  void becomeNative(SourceLoader loader) {
    loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
  }

  @override
  void buildOutlineExpressions({
    required ClassHierarchy classHierarchy,
    required SourceLibraryBuilder libraryBuilder,
    required DeclarationBuilder? declarationBuilder,
    required BodyBuilderContext bodyBuilderContext,
    required Annotatable annotatable,
    required Uri annotatableFileUri,
    required bool isClassInstanceMember,
  }) {
    buildMetadataForOutlineExpressions(
      libraryBuilder: libraryBuilder,
      scope: _fragment.enclosingScope,
      bodyBuilderContext: bodyBuilderContext,
      annotatable: annotatable,
      annotatableFileUri: annotatableFileUri,
      metadata: _fragment.metadata,
    );

    buildTypeParametersForOutlineExpressions(
      classHierarchy,
      libraryBuilder,
      bodyBuilderContext,
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
    );
    buildFormalsForOutlineExpressions(
      libraryBuilder,
      declarationBuilder,
      _fragment.declaredFormals,
      scope: _fragment.typeParameterScope,
      isClassInstanceMember: isClassInstanceMember,
    );
  }

  @override
  void buildOutlineNode({
    required SourceLibraryBuilder libraryBuilder,
    required NameScheme nameScheme,
    required BuildNodesCallback f,
    required PropertyReferences? references,
    required bool isAbstractOrExternal,
    required List<TypeParameter>? classTypeParameters,
  }) {
    FunctionNode function =
        new FunctionNode(
            isAbstractOrExternal ? null : new EmptyStatement(),
            asyncMarker: _fragment.asyncModifier,
          )
          ..fileOffset = _fragment.formalsOffset
          ..fileEndOffset = _fragment.endOffset;
    buildTypeParametersAndFormals(
      libraryBuilder,
      function,
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
      _fragment.declaredFormals,
      classTypeParameters: classTypeParameters,
      supportsTypeParameters: true,
    );
    if (_fragment.returnType is! InferableTypeBuilder) {
      function.returnType = _fragment.returnType.build(
        libraryBuilder,
        TypeUse.returnType,
      );
    }
    if (_fragment.declaredFormals?.length != 1 ||
        _fragment.declaredFormals![0].isOptionalPositional) {
      // Replace illegal parameters by single dummy parameter.
      // Do this after building the parameters, since the diet listener
      // assumes that parameters are built, even if illegal in number.
      VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
      function.positionalParameters.clear();
      function.positionalParameters.add(parameter);
      parameter.parent = function;
      function.namedParameters.clear();
      function.requiredParameterCount = 1;
    }
    MemberName memberName = nameScheme.getProcedureMemberName(
      ProcedureKind.Setter,
      _fragment.name,
    );
    Procedure procedure = _procedure =
        new Procedure(
            memberName.name,
            ProcedureKind.Setter,
            function,
            reference: references?.setterReference,
            fileUri: _fragment.fileUri,
          )
          ..fileStartOffset = _fragment.startOffset
          ..fileOffset = _fragment.nameOffset
          ..fileEndOffset = _fragment.endOffset
          ..isAbstract = _fragment.modifiers.isAbstract
          ..isExternal = _fragment.modifiers.isExternal
          ..isConst = _fragment.modifiers.isConst
          ..isStatic = _fragment.modifiers.isStatic
          ..isExtensionMember = _isExtensionMember
          ..isExtensionTypeMember = _isExtensionTypeMember;
    memberName.attachMember(procedure);

    f(kind: _builtMemberKind, member: procedure);
  }

  @override
  void checkTypes(
    SourceLibraryBuilder libraryBuilder,
    TypeEnvironment typeEnvironment, {
    required bool isAbstract,
    required bool isExternal,
  }) {
    List<SourceNominalParameterBuilder>? typeParameters = _fragment
        .declaredTypeParameters
        // Coverage-ignore(suite): Not run.
        ?.builders;
    // Coverage-ignore(suite): Not run.
    if (typeParameters != null && typeParameters.isNotEmpty) {
      checkTypeParameterDependencies(libraryBuilder, typeParameters);
    }
    libraryBuilder.checkInitializersInFormals(
      _fragment.declaredFormals,
      typeEnvironment,
      isAbstract: isAbstract,
      isExternal: isExternal,
    );
  }

  @override
  void checkVariance(
    SourceClassBuilder sourceClassBuilder,
    TypeEnvironment typeEnvironment,
  ) {
    sourceClassBuilder.checkVarianceInTypeParameters(
      typeEnvironment,
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
    );
    sourceClassBuilder.checkVarianceInFormals(
      typeEnvironment,
      _fragment.declaredFormals,
    );
    sourceClassBuilder.checkVarianceInReturnType(
      typeEnvironment,
      function.returnType,
      fileOffset: _fragment.nameOffset,
      fileUri: _fragment.fileUri,
    );
  }

  @override
  int computeDefaultTypes(ComputeDefaultTypeContext context) {
    bool hasErrors = context.reportSimplicityIssuesForTypeParameters(
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
    );
    context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
    if (_fragment.returnType is! OmittedTypeBuilder) {
      hasErrors |= context.reportInboundReferenceIssuesForType(
        _fragment.returnType,
      );
      context.recursivelyReportGenericFunctionTypesAsBoundsForType(
        _fragment.returnType,
      );
    }
    return context.computeDefaultTypesForVariables(
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
      inErrorRecovery: hasErrors,
    );
  }

  @override
  LocalScope createFormalParameterScope(LookupScope parent) {
    Map<String, VariableBuilder> local = {};
    List<FormalParameterBuilder>? formals = _fragment.declaredFormals;
    if (formals != null) {
      for (FormalParameterBuilder formal in formals) {
        if (formal.isWildcard) {
          continue;
        }
        local[formal.name] = formal;
      }
    }
    return new FormalParameterScope(local: local, parent: parent);
  }

  @override
  void ensureTypes(
    SourceLibraryBuilder libraryBuilder,
    ClassHierarchyBase hierarchy,
  ) {
    _fragment.returnType.build(
      libraryBuilder,
      TypeUse.returnType,
      hierarchy: hierarchy,
    );
    List<FormalParameterBuilder>? declaredFormals = _fragment.declaredFormals;
    if (declaredFormals != null) {
      for (FormalParameterBuilder formal in declaredFormals) {
        formal.type.build(
          libraryBuilder,
          TypeUse.parameterType,
          hierarchy: hierarchy,
        );
      }
    }
  }

  @override
  VariableDeclaration getFormalParameter(int index) =>
      _fragment.declaredFormals![index].variable!;
}

mixin _ExtensionInstanceSetterEncodingMixin implements SetterEncoding {
  Procedure? _procedure;

  @override
  List<SourceNominalParameterBuilder>? get clonedAndDeclaredTypeParameters =>
      _clonedDeclarationTypeParameters != null ||
          _fragment.declaredTypeParameters != null
      ? [
          ...?_clonedDeclarationTypeParameters,
          ...?_fragment
              .declaredTypeParameters
              // Coverage-ignore(suite): Not run.
              ?.builders,
        ]
      : null;

  @override
  List<FormalParameterBuilder>? get formals => [
    _thisFormal,
    ...?_fragment.declaredFormals,
  ];

  @override
  FunctionNode get function => _procedure!.function;

  @override
  List<TypeParameter>? get thisTypeParameters =>
      _clonedDeclarationTypeParameters != null ? function.typeParameters : null;

  @override
  VariableDeclaration? get thisVariable => _thisFormal.variable!;

  @override
  Procedure get writeTarget => _procedure!;

  BuiltMemberKind get _builtMemberKind;

  List<SourceNominalParameterBuilder>? get _clonedDeclarationTypeParameters;

  SetterFragment get _fragment;

  bool get _isExtensionMember;

  bool get _isExtensionTypeMember;

  FormalParameterBuilder get _thisFormal;

  @override
  // Coverage-ignore(suite): Not run.
  void becomeNative(SourceLoader loader) {
    loader.addNativeAnnotation(_procedure!, _fragment.nativeMethodName!);
  }

  @override
  void buildOutlineExpressions({
    required ClassHierarchy classHierarchy,
    required SourceLibraryBuilder libraryBuilder,
    required DeclarationBuilder? declarationBuilder,
    required BodyBuilderContext bodyBuilderContext,
    required Annotatable annotatable,
    required Uri annotatableFileUri,
    required bool isClassInstanceMember,
  }) {
    buildMetadataForOutlineExpressions(
      libraryBuilder: libraryBuilder,
      scope: _fragment.enclosingScope,
      bodyBuilderContext: bodyBuilderContext,
      annotatable: annotatable,
      annotatableFileUri: annotatableFileUri,
      metadata: _fragment.metadata,
    );

    buildTypeParametersForOutlineExpressions(
      classHierarchy,
      libraryBuilder,
      bodyBuilderContext,
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
    );
    buildFormalsForOutlineExpressions(
      libraryBuilder,
      declarationBuilder,
      _fragment.declaredFormals,
      scope: _fragment.typeParameterScope,
      isClassInstanceMember: isClassInstanceMember,
    );

    buildTypeParametersForOutlineExpressions(
      classHierarchy,
      libraryBuilder,
      bodyBuilderContext,
      _clonedDeclarationTypeParameters,
    );
    buildFormalForOutlineExpressions(
      libraryBuilder,
      declarationBuilder,
      _thisFormal,
      scope: _fragment.typeParameterScope,
      isClassInstanceMember: isClassInstanceMember,
    );
  }

  @override
  void buildOutlineNode({
    required SourceLibraryBuilder libraryBuilder,
    required NameScheme nameScheme,
    required BuildNodesCallback f,
    required PropertyReferences? references,
    required bool isAbstractOrExternal,
    required List<TypeParameter>? classTypeParameters,
  }) {
    List<TypeParameter>? typeParameters;
    if (_clonedDeclarationTypeParameters != null) {
      typeParameters = [];
      // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both required
      // and unnecessary.
      // ignore: unnecessary_non_null_assertion
      for (NominalParameterBuilder t in _clonedDeclarationTypeParameters!) {
        typeParameters.add(t.parameter);
      }
    }
    FunctionNode function =
        new FunctionNode(
            isAbstractOrExternal ? null : new EmptyStatement(),
            typeParameters: typeParameters,
            positionalParameters: [_thisFormal.build(libraryBuilder)],
            asyncMarker: _fragment.asyncModifier,
          )
          ..fileOffset = _fragment.formalsOffset
          ..fileEndOffset = _fragment.endOffset;
    buildTypeParametersAndFormals(
      libraryBuilder,
      function,
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
      _fragment.declaredFormals,
      classTypeParameters: classTypeParameters,
      supportsTypeParameters: true,
    );
    // TODO(johnniwinther): We should have a consistent normalization strategy.
    // We ensure that setters have 1 parameter, but for getters we include all
    // declared parameters.
    if ((_fragment.declaredFormals?.length != 1 ||
        _fragment.declaredFormals![0].isOptionalPositional)) {
      // Replace illegal parameters by single dummy parameter (after #this).
      // Do this after building the parameters, since the diet listener
      // assumes that parameters are built, even if illegal in number.
      VariableDeclaration thisParameter = function.positionalParameters[0];
      VariableDeclaration parameter = new VariableDeclarationImpl("#synthetic");
      function.positionalParameters.clear();
      function.positionalParameters.add(thisParameter);
      function.positionalParameters.add(parameter);
      parameter.parent = function;
      function.namedParameters.clear();
      function.requiredParameterCount = 2;
    }
    if (_fragment.returnType is! InferableTypeBuilder) {
      function.returnType = _fragment.returnType.build(
        libraryBuilder,
        TypeUse.returnType,
      );
    }

    MemberName memberName = nameScheme.getProcedureMemberName(
      ProcedureKind.Setter,
      _fragment.name,
    );
    Procedure procedure = _procedure =
        new Procedure(
            memberName.name,
            ProcedureKind.Method,
            function,
            reference: references?.setterReference,
            fileUri: _fragment.fileUri,
          )
          ..fileStartOffset = _fragment.startOffset
          ..fileOffset = _fragment.nameOffset
          ..fileEndOffset = _fragment.endOffset
          ..isAbstract = _fragment.modifiers.isAbstract
          ..isExternal = _fragment.modifiers.isExternal
          ..isConst = _fragment.modifiers.isConst
          ..isStatic = true
          ..isExtensionMember = _isExtensionMember
          ..isExtensionTypeMember = _isExtensionTypeMember;
    memberName.attachMember(procedure);

    f(kind: _builtMemberKind, member: procedure);
  }

  @override
  void checkTypes(
    SourceLibraryBuilder libraryBuilder,
    TypeEnvironment typeEnvironment, {
    required bool isAbstract,
    required bool isExternal,
  }) {
    List<SourceNominalParameterBuilder>? typeParameters = _fragment
        .declaredTypeParameters
        // Coverage-ignore(suite): Not run.
        ?.builders;
    // Coverage-ignore(suite): Not run.
    if (typeParameters != null && typeParameters.isNotEmpty) {
      checkTypeParameterDependencies(libraryBuilder, typeParameters);
    }
    libraryBuilder.checkInitializersInFormals(
      _fragment.declaredFormals,
      typeEnvironment,
      isAbstract: isAbstract,
      isExternal: isExternal,
    );
  }

  @override
  // Coverage-ignore(suite): Not run.
  void checkVariance(
    SourceClassBuilder sourceClassBuilder,
    TypeEnvironment typeEnvironment,
  ) {
    sourceClassBuilder.checkVarianceInTypeParameters(
      typeEnvironment,
      _fragment.declaredTypeParameters?.builders,
    );
    sourceClassBuilder.checkVarianceInFormals(
      typeEnvironment,
      _fragment.declaredFormals,
    );
    sourceClassBuilder.checkVarianceInReturnType(
      typeEnvironment,
      function.returnType,
      fileOffset: _fragment.nameOffset,
      fileUri: _fragment.fileUri,
    );
  }

  @override
  int computeDefaultTypes(ComputeDefaultTypeContext context) {
    bool hasErrors = context.reportSimplicityIssuesForTypeParameters(
      _fragment
          .declaredTypeParameters
          // Coverage-ignore(suite): Not run.
          ?.builders,
    );
    context.reportGenericFunctionTypesForFormals(_fragment.declaredFormals);
    if (_fragment.returnType is! OmittedTypeBuilder) {
      hasErrors |= context.reportInboundReferenceIssuesForType(
        _fragment.returnType,
      );
      context.recursivelyReportGenericFunctionTypesAsBoundsForType(
        _fragment.returnType,
      );
    }
    if (_clonedDeclarationTypeParameters != null &&
        _fragment.declaredTypeParameters != null) {
      // Coverage-ignore-block(suite): Not run.
      // We need to compute all default types together since they might be
      // interdependent.
      return context.computeDefaultTypesForVariables([
        // TODO(johnniwinther): Ambivalent analyzer. `!` seems to be both
        //  required and unnecessary.
        // ignore: unnecessary_non_null_assertion
        ..._clonedDeclarationTypeParameters!,
        ..._fragment.declaredTypeParameters!.builders,
      ], inErrorRecovery: hasErrors);
    } else if (_clonedDeclarationTypeParameters != null) {
      return context.computeDefaultTypesForVariables(
        _clonedDeclarationTypeParameters,
        inErrorRecovery: hasErrors,
      );
    } else {
      return context.computeDefaultTypesForVariables(
        _fragment
            .declaredTypeParameters
            // Coverage-ignore(suite): Not run.
            ?.builders,
        inErrorRecovery: hasErrors,
      );
    }
  }

  @override
  LocalScope createFormalParameterScope(LookupScope parent) {
    Map<String, VariableBuilder> local = {};

    assert(!_thisFormal.isWildcard);
    local[_thisFormal.name] = _thisFormal;

    List<FormalParameterBuilder>? formals = _fragment.declaredFormals;
    if (formals != null) {
      for (FormalParameterBuilder formal in formals) {
        if (formal.isWildcard) {
          continue;
        }
        local[formal.name] = formal;
      }
    }
    return new FormalParameterScope(local: local, parent: parent);
  }

  @override
  // Coverage-ignore(suite): Not run.
  void ensureTypes(
    SourceLibraryBuilder libraryBuilder,
    ClassHierarchyBase hierarchy,
  ) {
    _fragment.returnType.build(
      libraryBuilder,
      TypeUse.fieldType,
      hierarchy: hierarchy,
    );
    _thisFormal.type.build(
      libraryBuilder,
      TypeUse.parameterType,
      hierarchy: hierarchy,
    );
    List<FormalParameterBuilder>? declaredFormals = _fragment.declaredFormals;
    if (declaredFormals != null) {
      for (FormalParameterBuilder formal in declaredFormals) {
        formal.type.build(
          libraryBuilder,
          TypeUse.parameterType,
          hierarchy: hierarchy,
        );
      }
    }
  }

  @override
  VariableDeclaration getFormalParameter(int index) =>
      _fragment.declaredFormals![index].variable!;
}
