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

library fasta.source_type_alias_builder;

import 'package:front_end/src/fasta/kernel/expression_generator_helper.dart';
import 'package:kernel/ast.dart';

import 'package:kernel/core_types.dart';

import 'package:kernel/type_algebra.dart'
    show FreshTypeParameters, getFreshTypeParameters;

import 'package:kernel/type_environment.dart';

import '../fasta_codes.dart'
    show noLength, templateCyclicTypedef, templateTypeArgumentMismatch;

import '../problems.dart' show unhandled;
import '../scope.dart';

import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';

import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/kernel_helper.dart';

import '../util/helpers.dart';

import 'source_library_builder.dart' show SourceLibraryBuilder;

class SourceTypeAliasBuilder extends TypeAliasBuilderImpl {
  @override
  final TypeBuilder? type;

  final List<TypeVariableBuilder>? _typeVariables;

  /// The [Typedef] built by this builder.
  @override
  final Typedef typedef;

  @override
  DartType? thisType;

  @override
  Map<Name, Procedure>? tearOffs;

  SourceTypeAliasBuilder(
      List<MetadataBuilder>? metadata,
      String name,
      this._typeVariables,
      this.type,
      SourceLibraryBuilder parent,
      int charOffset,
      {Typedef? typedef,
      Typedef? referenceFrom})
      : typedef = typedef ??
            (new Typedef(name, null,
                typeParameters: TypeVariableBuilder.typeParametersFromBuilders(
                    _typeVariables),
                fileUri: parent.library.fileUri,
                reference: referenceFrom?.reference)
              ..fileOffset = charOffset),
        super(metadata, name, parent, charOffset);

  @override
  SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;

  @override
  List<TypeVariableBuilder>? get typeVariables => _typeVariables;

  @override
  int varianceAt(int index) => typeVariables![index].parameter.variance;

  @override
  bool get fromDill => false;

  @override
  int get typeVariablesCount => typeVariables?.length ?? 0;

  @override
  bool get isNullAlias {
    TypeDeclarationBuilder? typeDeclarationBuilder = type?.declaration;
    return typeDeclarationBuilder is ClassBuilder &&
        typeDeclarationBuilder.isNullClass;
  }

  Typedef build(SourceLibraryBuilder libraryBuilder) {
    typedef.type ??= buildThisType();

    TypeBuilder? type = this.type;
    if (type is FunctionTypeBuilder) {
      List<TypeParameter> typeParameters = new List<TypeParameter>.generate(
          type.typeVariables?.length ?? 0,
          (int i) => type.typeVariables![i].parameter,
          growable: false);
      FreshTypeParameters freshTypeParameters =
          getFreshTypeParameters(typeParameters);
      for (int i = 0; i < freshTypeParameters.freshTypeParameters.length; i++) {
        TypeParameter typeParameter =
            freshTypeParameters.freshTypeParameters[i];
        typedef.typeParametersOfFunctionType
            .add(typeParameter..parent = typedef);
      }

      if (type.formals != null) {
        for (FormalParameterBuilder formal in type.formals!) {
          VariableDeclaration parameter = formal.build(libraryBuilder, 0);
          parameter.type = freshTypeParameters.substitute(parameter.type);
          if (formal.isNamed) {
            typedef.namedParameters.add(parameter);
          } else {
            typedef.positionalParameters.add(parameter);
          }
          parameter.parent = typedef;
        }
      }
    } else if (type is NamedTypeBuilder || type is FixedTypeBuilder) {
      // No error, but also no additional setup work.
      // ignore: unnecessary_null_comparison
    } else if (type != null) {
      unhandled("${type.fullNameForErrors}", "build", charOffset, fileUri);
    }

    return typedef;
  }

  @override
  DartType buildThisType() {
    if (thisType != null) {
      if (identical(thisType, pendingTypeAliasMarker)) {
        thisType = cyclicTypeAliasMarker;
        library.addProblem(templateCyclicTypedef.withArguments(name),
            charOffset, noLength, fileUri);
        return const InvalidType();
      } else if (identical(thisType, cyclicTypeAliasMarker)) {
        return const InvalidType();
      }
      return thisType!;
    }
    // It is a compile-time error for an alias (typedef) to refer to itself. We
    // detect cycles by detecting recursive calls to this method using an
    // instance of InvalidType that isn't identical to `const InvalidType()`.
    thisType = pendingTypeAliasMarker;
    TypeBuilder? type = this.type;
    // ignore: unnecessary_null_comparison
    if (type != null) {
      DartType builtType =
          type.build(library, origin: thisTypedefType(typedef, library));
      // ignore: unnecessary_null_comparison
      if (builtType != null) {
        if (typeVariables != null) {
          for (TypeVariableBuilder tv in typeVariables!) {
            // Follow bound in order to find all cycles
            tv.bound?.build(library);
          }
        }
        if (identical(thisType, cyclicTypeAliasMarker)) {
          return thisType = const InvalidType();
        } else {
          return thisType = builtType;
        }
      } else {
        return thisType = const InvalidType();
      }
    }
    return thisType = const InvalidType();
  }

  TypedefType thisTypedefType(Typedef typedef, LibraryBuilder clientLibrary) {
    // At this point the bounds of `typedef.typeParameters` may not be assigned
    // yet, so [getAsTypeArguments] may crash trying to compute the nullability
    // of the created types from the bounds.  To avoid that, we use "dynamic"
    // for the bound of all boundless variables and add them to the list for
    // being recomputed later, when the bounds are assigned.
    List<DartType> bounds =
        new List<DartType>.generate(typedef.typeParameters.length, (int i) {
      DartType bound = typedef.typeParameters[i].bound;
      if (identical(bound, TypeParameter.unsetBoundSentinel)) {
        typedef.typeParameters[i].bound = const DynamicType();
      }
      return bound;
    }, growable: false);
    for (int i = 0; i < bounds.length; ++i) {}
    List<DartType> asTypeArguments =
        getAsTypeArguments(typedef.typeParameters, clientLibrary.library);
    TypedefType result =
        new TypedefType(typedef, clientLibrary.nonNullable, asTypeArguments);
    for (int i = 0; i < bounds.length; ++i) {
      if (identical(bounds[i], TypeParameter.unsetBoundSentinel)) {
        // If the bound is not assigned yet, put the corresponding
        // type-parameter type into the list for the nullability re-computation.
        // At this point, [parent] should be a [SourceLibraryBuilder] because
        // otherwise it's a compiled library loaded from a dill file, and the
        // bounds should have been assigned.
        library.registerPendingNullability(
            _typeVariables![i].fileUri!,
            _typeVariables![i].charOffset,
            asTypeArguments[i] as TypeParameterType);
      }
    }
    return result;
  }

  @override
  List<DartType> buildTypeArguments(
      LibraryBuilder library, List<TypeBuilder>? arguments,
      {bool? nonInstanceContext}) {
    if (arguments == null && typeVariables == null) {
      return <DartType>[];
    }

    if (arguments == null && typeVariables != null) {
      List<DartType> result = new List<DartType>.generate(typeVariables!.length,
          (int i) => typeVariables![i].defaultType!.build(library),
          growable: true);
      if (library is SourceLibraryBuilder) {
        library.inferredTypes.addAll(result);
      }
      return result;
    }

    if (arguments != null && arguments.length != typeVariablesCount) {
      // That should be caught and reported as a compile-time error earlier.
      return unhandled(
          templateTypeArgumentMismatch
              .withArguments(typeVariablesCount)
              .problemMessage,
          "buildTypeArguments",
          -1,
          null);
    }

    // arguments.length == typeVariables.length
    return new List<DartType>.generate(
        arguments!.length, (int i) => arguments[i].build(library),
        growable: true);
  }

  void checkTypesInOutline(TypeEnvironment typeEnvironment) {
    library.checkBoundsInTypeParameters(
        typeEnvironment, typedef.typeParameters, fileUri);
    library.checkBoundsInType(
        typedef.type!, typeEnvironment, fileUri, type?.charOffset ?? charOffset,
        allowSuperBounded: false);
  }

  void buildOutlineExpressions(
      SourceLibraryBuilder library,
      CoreTypes coreTypes,
      List<DelayedActionPerformer> delayedActionPerformers,
      List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
    MetadataBuilder.buildAnnotations(
        typedef, metadata, library, null, null, fileUri, library.scope);
    if (typeVariables != null) {
      for (int i = 0; i < typeVariables!.length; i++) {
        typeVariables![i].buildOutlineExpressions(
            library,
            null,
            null,
            coreTypes,
            delayedActionPerformers,
            computeTypeParameterScope(library.scope));
      }
    }
    _tearOffDependencies?.forEach((Procedure tearOff, Member target) {
      InterfaceType targetType = typedef.type as InterfaceType;
      synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
          new Map<TypeParameter, DartType>.fromIterables(
              target.enclosingClass!.typeParameters, targetType.typeArguments),
          target.function!,
          tearOff.function));
    });
  }

  Scope computeTypeParameterScope(Scope parent) {
    if (typeVariables == null) return parent;
    Map<String, Builder> local = <String, Builder>{};
    for (TypeVariableBuilder variable in typeVariables!) {
      local[variable.name] = variable;
    }
    return new Scope(
        local: local,
        parent: parent,
        debugName: "type parameter",
        isModifiable: false);
  }

  Map<Procedure, Member>? _tearOffDependencies;

  void buildTypedefTearOffs(
      SourceLibraryBuilder library, void Function(Procedure) f) {
    TypeDeclarationBuilder? declaration = unaliasDeclaration(null);
    DartType? targetType = typedef.type;
    if (declaration is ClassBuilder &&
        targetType is InterfaceType &&
        typedef.typeParameters.isNotEmpty &&
        !isProperRenameForClass(
            library.loader.typeEnvironment, typedef, library.library)) {
      tearOffs = {};
      _tearOffDependencies = {};
      declaration
          .forEachConstructor((String constructorName, MemberBuilder builder) {
        Member? target = builder.invokeTarget;
        if (target != null) {
          if (target is Procedure && target.isRedirectingFactory) {
            target = builder.readTarget!;
          }
          Name targetName =
              new Name(constructorName, declaration.library.library);
          Reference? tearOffReference;
          if (library.referencesFromIndexed != null) {
            tearOffReference = library.referencesFromIndexed!
                .lookupGetterReference(typedefTearOffName(name, constructorName,
                    library.referencesFromIndexed!.library));
          }

          Procedure tearOff = tearOffs![targetName] =
              createTypedefTearOffProcedure(name, constructorName, library,
                  target.fileUri, target.fileOffset, tearOffReference);
          _tearOffDependencies![tearOff] = target;

          buildTypedefTearOffProcedure(tearOff, target, declaration.cls,
              typedef.typeParameters, targetType.typeArguments, library);
          f(tearOff);
        }
      });
    }
  }
}
