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

// @dart = 2.9

library fasta.type_variable_builder;

import 'package:kernel/ast.dart'
    show DartType, Nullability, TypeParameter, TypeParameterType;
import 'package:kernel/core_types.dart';

import '../fasta_codes.dart'
    show
        templateInternalProblemUnfinishedTypeVariable,
        templateTypeArgumentsOnTypeVariable;

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

import 'class_builder.dart';
import 'declaration_builder.dart';
import 'library_builder.dart';
import 'member_builder.dart';
import 'metadata_builder.dart';
import 'named_type_builder.dart';
import 'nullability_builder.dart';
import 'type_builder.dart';
import 'type_declaration_builder.dart';

class TypeVariableBuilder extends TypeDeclarationBuilderImpl {
  TypeBuilder bound;

  TypeBuilder defaultType;

  final TypeParameter actualParameter;

  TypeVariableBuilder actualOrigin;

  final bool isExtensionTypeParameter;

  TypeVariableBuilder(String name, SourceLibraryBuilder compilationUnit,
      int charOffset, Uri fileUri,
      {this.bound,
      this.isExtensionTypeParameter: false,
      int variableVariance,
      List<MetadataBuilder> metadata})
      : actualParameter = new TypeParameter(name, null)
          ..fileOffset = charOffset
          ..variance = variableVariance,
        super(metadata, 0, name, compilationUnit, charOffset, fileUri);

  TypeVariableBuilder.fromKernel(
      TypeParameter parameter, LibraryBuilder compilationUnit)
      : actualParameter = parameter,
        // TODO(johnniwinther): Do we need to support synthesized type
        //  parameters from kernel?
        this.isExtensionTypeParameter = false,
        super(null, 0, parameter.name, compilationUnit, parameter.fileOffset);

  bool get isTypeVariable => true;

  String get debugName => "TypeVariableBuilder";

  StringBuffer printOn(StringBuffer buffer) {
    buffer.write(name);
    if (bound != null) {
      buffer.write(" extends ");
      bound.printOn(buffer);
    }
    return buffer;
  }

  String toString() => "${printOn(new StringBuffer())}";

  TypeVariableBuilder get origin => actualOrigin ?? this;

  /// The [TypeParameter] built by this builder.
  TypeParameter get parameter => origin.actualParameter;

  int get variance => parameter.variance;

  void set variance(int value) {
    parameter.variance = value;
  }

  DartType buildType(LibraryBuilder library,
      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
      [bool notInstanceContext]) {
    if (arguments != null) {
      int charOffset = -1; // TODO(ahe): Provide these.
      Uri fileUri = null; // TODO(ahe): Provide these.
      library.addProblem(
          templateTypeArgumentsOnTypeVariable.withArguments(name),
          charOffset,
          name.length,
          fileUri);
    }
    // If the bound is not set yet, the actual value is not important yet as it
    // will be set later.
    bool needsPostUpdate = false;
    Nullability nullability;
    if (nullabilityBuilder.isOmitted) {
      if (!identical(parameter.bound, TypeParameter.unsetBoundSentinel)) {
        nullability = library.isNonNullableByDefault
            ? TypeParameterType.computeNullabilityFromBound(parameter)
            : Nullability.legacy;
      } else {
        nullability = Nullability.legacy;
        needsPostUpdate = true;
      }
    } else {
      nullability = nullabilityBuilder.build(library);
    }
    DartType type = buildTypesWithBuiltArguments(library, nullability, null);
    if (needsPostUpdate) {
      if (library is SourceLibraryBuilder) {
        library.registerPendingNullability(fileUri, charOffset, type);
      } else {
        library.addProblem(
            templateInternalProblemUnfinishedTypeVariable.withArguments(
                name, library?.importUri),
            charOffset,
            name.length,
            fileUri);
      }
    }
    return type;
  }

  DartType buildTypesWithBuiltArguments(LibraryBuilder library,
      Nullability nullability, List<DartType> arguments) {
    if (arguments != null) {
      int charOffset = -1; // TODO(ahe): Provide these.
      Uri fileUri = null; // TODO(ahe): Provide these.
      library.addProblem(
          templateTypeArgumentsOnTypeVariable.withArguments(name),
          charOffset,
          name.length,
          fileUri);
    }
    return new TypeParameterType(parameter, nullability);
  }

  TypeBuilder asTypeBuilder() {
    return new NamedTypeBuilder(
        name, const NullabilityBuilder.omitted(), null, fileUri, charOffset)
      ..bind(this);
  }

  void finish(
      LibraryBuilder library, ClassBuilder object, TypeBuilder dynamicType) {
    if (isPatch) return;
    // TODO(jensj): Provide correct notInstanceContext.
    DartType objectType =
        object.buildType(library, library.nullableBuilder, null, null);
    if (identical(parameter.bound, TypeParameter.unsetBoundSentinel)) {
      parameter.bound = bound?.build(library) ?? objectType;
    }
    // If defaultType is not set, initialize it to dynamic, unless the bound is
    // explicitly specified as Object, in which case defaultType should also be
    // Object. This makes sure instantiation of generic function types with an
    // explicit Object bound results in Object as the instantiated type.
    if (identical(
        parameter.defaultType, TypeParameter.unsetDefaultTypeSentinel)) {
      parameter.defaultType = defaultType?.build(library) ??
          (bound != null && parameter.bound == objectType
              ? objectType
              : dynamicType.build(library));
    }
  }

  void applyPatch(covariant TypeVariableBuilder patch) {
    patch.actualOrigin = this;
  }

  TypeVariableBuilder clone(List<TypeBuilder> newTypes) {
    // TODO(dmitryas): Figure out if using [charOffset] here is a good idea.
    // An alternative is to use the offset of the node the cloned type variable
    // is declared on.
    return new TypeVariableBuilder(name, parent, charOffset, fileUri,
        bound: bound.clone(newTypes), variableVariance: variance);
  }

  void buildOutlineExpressions(
      LibraryBuilder libraryBuilder,
      DeclarationBuilder classOrExtensionBuilder,
      MemberBuilder memberBuilder,
      CoreTypes coreTypes,
      List<DelayedActionPerformer> delayedActionPerformers) {
    MetadataBuilder.buildAnnotations(parameter, metadata, libraryBuilder,
        classOrExtensionBuilder, memberBuilder, fileUri);
  }

  @override
  bool operator ==(Object other) {
    return other is TypeVariableBuilder && parameter == other.parameter;
  }

  @override
  int get hashCode => parameter.hashCode;

  static List<TypeParameter> typeParametersFromBuilders(
      List<TypeVariableBuilder> builders) {
    if (builders == null) return null;
    List<TypeParameter> result =
        new List<TypeParameter>.filled(builders.length, null, growable: true);
    for (int i = 0; i < builders.length; i++) {
      result[i] = builders[i].parameter;
    }
    return result;
  }
}
