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

import 'package:kernel/ast.dart';

import '../fasta_codes.dart'
    show
        LocatedMessage,
        Message,
        Severity,
        Template,
        messageNotATypeContext,
        messageTypeVariableInStaticContext,
        messageTypedefCause,
        noLength,
        templateExperimentNotEnabled,
        templateExtendingRestricted,
        templateNotAType,
        templateSupertypeIsIllegal,
        templateSupertypeIsIllegalAliased,
        templateSupertypeIsNullableAliased,
        templateSupertypeIsTypeVariable,
        templateTypeArgumentMismatch,
        templateTypeArgumentsOnTypeVariable,
        templateTypeNotFound;

import '../identifiers.dart' show Identifier, QualifiedName, flattenName;

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

import '../scope.dart';

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

import 'builder.dart';
import 'builtin_type_declaration_builder.dart';
import 'class_builder.dart';
import 'invalid_type_declaration_builder.dart';
import 'library_builder.dart';
import 'nullability_builder.dart';
import 'prefix_builder.dart';
import 'type_alias_builder.dart';
import 'type_builder.dart';
import 'type_declaration_builder.dart';
import 'type_variable_builder.dart';
import 'void_type_declaration_builder.dart';

/// Enum used to determine how instance type variable access is allowed.
enum InstanceTypeVariableAccessState {
  /// Instance type variable access is allowed.
  ///
  /// This is used for valid references to instance type variables, like
  ///
  ///     class Class<T> {
  ///       void instanceMethod(T t) {}
  ///     }
  Allowed,

  /// Instance type variable access is disallowed and results in a compile-time
  /// error.
  ///
  /// This is used for static references to instance type variables, like
  ///
  ///     class Class<T> {
  ///       static void staticMethod(T t) {}
  ///     }
  ///
  /// The type is resolved as an [InvalidType].
  Disallowed,

  /// Instance type variable access is invalid since it occurs in an invalid
  /// context. The occurrence _doesn't_ result in a compile-time error.
  ///
  /// This is used for references to instance type variables where they might
  /// be valid if the context where, like
  ///
  ///     class Extension<T> {
  ///       T field; // Instance extension fields are not allowed.
  ///     }
  ///
  /// The type is resolved as an [InvalidType].
  Invalid,

  /// Instance type variable access is unexpected and results in an assertion
  /// failure.
  ///
  /// This is used for [NamedTypeBuilder]s for known non-type variable types,
  /// like for `Object` and `String`.
  Unexpected,
}

class NamedTypeBuilder extends TypeBuilder {
  @override
  final Object name;

  List<TypeBuilder>? arguments;

  @override
  final NullabilityBuilder nullabilityBuilder;

  @override
  final Uri? fileUri;

  @override
  final int? charOffset;

  @override
  TypeDeclarationBuilder? declaration;

  final InstanceTypeVariableAccessState instanceTypeVariableAccess;

  NamedTypeBuilder(this.name, this.nullabilityBuilder, this.arguments,
      this.fileUri, this.charOffset,
      {required this.instanceTypeVariableAccess});

  NamedTypeBuilder.fromTypeDeclarationBuilder(
      TypeDeclarationBuilder this.declaration, this.nullabilityBuilder,
      {this.arguments,
      this.fileUri,
      this.charOffset,
      required this.instanceTypeVariableAccess})
      : this.name = declaration.name;

  @override
  bool get isVoidType => declaration is VoidTypeDeclarationBuilder;

  @override
  void bind(TypeDeclarationBuilder declaration) {
    this.declaration = declaration.origin;
  }

  int get nameOffset {
    if (name is Identifier) {
      Identifier identifier = name as Identifier;
      return identifier.charOffset;
    }
    return -1; // TODO(eernst): make it possible to get offset.
  }

  int get nameLength {
    if (name is Identifier) {
      Identifier identifier = name as Identifier;
      return identifier.name.length;
    } else if (name is String) {
      String nameString = name as String;
      return nameString.length;
    } else {
      return noLength;
    }
  }

  @override
  void resolveIn(
      Scope scope, int charOffset, Uri fileUri, LibraryBuilder library) {
    if (declaration != null) return;
    final Object name = this.name;
    Builder? member;
    if (name is QualifiedName) {
      Object qualifier = name.qualifier;
      String prefixName = flattenName(qualifier, charOffset, fileUri);
      Builder? prefix = scope.lookup(prefixName, charOffset, fileUri);
      if (prefix is PrefixBuilder) {
        member = prefix.lookup(name.name, name.charOffset, fileUri);
      }
    } else if (name is String) {
      member = scope.lookup(name, charOffset, fileUri);
    } else {
      unhandled("${name.runtimeType}", "resolveIn", charOffset, fileUri);
    }
    if (member is TypeVariableBuilder) {
      declaration = member.origin;
      if (arguments != null) {
        String typeName;
        int typeNameOffset;
        if (name is Identifier) {
          typeName = name.name;
          typeNameOffset = name.charOffset;
        } else {
          typeName = name as String;
          typeNameOffset = charOffset;
        }
        Message message =
            templateTypeArgumentsOnTypeVariable.withArguments(typeName);
        library.addProblem(message, typeNameOffset, typeName.length, fileUri);
        declaration = buildInvalidTypeDeclarationBuilder(
            message.withLocation(fileUri, typeNameOffset, typeName.length));
      }
      return;
    } else if (member is TypeDeclarationBuilder) {
      declaration = member.origin;
      if (!declaration!.isExtension ||
          library is SourceLibraryBuilder &&
              library.enableExtensionTypesInLibrary) {
        return;
      }
    }
    Template<Message Function(String name)> template =
        member == null ? templateTypeNotFound : templateNotAType;
    String flatName = flattenName(name, charOffset, fileUri);
    int length =
        name is Identifier ? name.endCharOffset - charOffset : flatName.length;
    Message message;
    List<LocatedMessage>? context;
    if (member == null) {
      template = templateTypeNotFound;
      message = template.withArguments(flatName);
    } else if (declaration != null &&
        declaration!.isExtension &&
        library is SourceLibraryBuilder &&
        !library.enableExtensionTypesInLibrary) {
      message = templateExperimentNotEnabled.withArguments('extension-types',
          library.enableExtensionTypesVersionInLibrary.toText());
    } else {
      template = templateNotAType;
      context = <LocatedMessage>[
        messageNotATypeContext.withLocation(member.fileUri!, member.charOffset,
            name is Identifier ? name.name.length : "$name".length)
      ];
      message = template.withArguments(flatName);
    }
    library.addProblem(message, charOffset, length, fileUri, context: context);
    declaration = buildInvalidTypeDeclarationBuilder(
        message.withLocation(fileUri, charOffset, length),
        context: context);
  }

  @override
  void check(LibraryBuilder library, int charOffset, Uri fileUri) {
    if (arguments != null &&
        arguments!.length != declaration!.typeVariablesCount) {
      Message message = templateTypeArgumentMismatch
          .withArguments(declaration!.typeVariablesCount);
      library.addProblem(message, charOffset, noLength, fileUri);
      declaration = buildInvalidTypeDeclarationBuilder(
          message.withLocation(fileUri, charOffset, noLength));
    }
  }

  @override
  String get debugName => "NamedTypeBuilder";

  @override
  StringBuffer printOn(StringBuffer buffer) {
    buffer.write(flattenName(name, charOffset ?? TreeNode.noOffset, fileUri));
    if (arguments?.isEmpty ?? true) return buffer;
    buffer.write("<");
    bool first = true;
    for (TypeBuilder t in arguments!) {
      if (!first) buffer.write(", ");
      first = false;
      t.printOn(buffer);
    }
    buffer.write(">");
    nullabilityBuilder.writeNullabilityOn(buffer);
    return buffer;
  }

  InvalidTypeDeclarationBuilder buildInvalidTypeDeclarationBuilder(
      LocatedMessage message,
      {List<LocatedMessage>? context}) {
    // TODO(ahe): Consider if it makes sense to pass a QualifiedName to
    // InvalidTypeBuilder?
    return new InvalidTypeDeclarationBuilder(
        flattenName(name, message.charOffset, message.uri), message,
        context: context);
  }

  Supertype? handleInvalidSupertype(
      LibraryBuilder library, int charOffset, Uri fileUri) {
    Template<Message Function(String name)> template =
        declaration!.isTypeVariable
            ? templateSupertypeIsTypeVariable
            : templateSupertypeIsIllegal;
    library.addProblem(template.withArguments(fullNameForErrors), charOffset,
        noLength, fileUri);
    return null;
  }

  Supertype? handleInvalidAliasedSupertype(
      LibraryBuilder library,
      int charOffset,
      Uri fileUri,
      TypeAliasBuilder aliasBuilder,
      DartType type) {
    // Don't report the error in case of InvalidType. An error has already been
    // reported in this case.
    if (type is InvalidType) return null;

    Message message;
    if (declaration!.isTypeVariable) {
      message =
          templateSupertypeIsTypeVariable.withArguments(fullNameForErrors);
    } else
    // ignore: unnecessary_null_comparison
    if (type != null && type.nullability == Nullability.nullable) {
      message = templateSupertypeIsNullableAliased.withArguments(
          fullNameForErrors, type, library.isNonNullableByDefault);
    } else {
      message = templateSupertypeIsIllegalAliased.withArguments(
          fullNameForErrors, type, library.isNonNullableByDefault);
    }
    library.addProblem(message, charOffset, noLength, fileUri, context: [
      messageTypedefCause.withLocation(
          aliasBuilder.fileUri, aliasBuilder.charOffset, noLength),
    ]);
    return null;
  }

  @override
  DartType build(LibraryBuilder library, {TypedefType? origin}) {
    return buildInternal(library, origin: origin, forTypeLiteral: false);
  }

  @override
  DartType buildTypeLiteralType(LibraryBuilder library, {TypedefType? origin}) {
    return buildInternal(library, origin: origin, forTypeLiteral: true);
  }

  DartType declarationBuildType(LibraryBuilder library,
      {required bool forTypeLiteral}) {
    if (forTypeLiteral) {
      return declaration!
          .buildTypeLiteralType(library, nullabilityBuilder, arguments);
    } else {
      return declaration!.buildType(library, nullabilityBuilder, arguments);
    }
  }

  // TODO(johnniwinther): Store [origin] on the built type.
  DartType buildInternal(LibraryBuilder library,
      {TypedefType? origin, required bool forTypeLiteral}) {
    assert(declaration != null, "Declaration has not been resolved on $this.");
    if (declaration!.isTypeVariable) {
      TypeVariableBuilder typeParameterBuilder =
          declaration as TypeVariableBuilder;
      TypeParameter typeParameter = typeParameterBuilder.parameter;
      if (typeParameter.parent is Class || typeParameter.parent is Extension) {
        switch (instanceTypeVariableAccess) {
          case InstanceTypeVariableAccessState.Disallowed:
            library.addProblem(
                messageTypeVariableInStaticContext,
                charOffset ?? TreeNode.noOffset,
                noLength,
                fileUri ?? library.fileUri);
            return const InvalidType();
          case InstanceTypeVariableAccessState.Invalid:
            return const InvalidType();
          case InstanceTypeVariableAccessState.Unexpected:
            assert(false,
                "Unexpected instance type variable $typeParameterBuilder");
            break;
          case InstanceTypeVariableAccessState.Allowed:
            break;
        }
      }
    }

    if (library is SourceLibraryBuilder) {
      int uncheckedTypedefTypeCount = library.uncheckedTypedefTypes.length;
      DartType builtType =
          declarationBuildType(library, forTypeLiteral: forTypeLiteral);
      // Set locations for new unchecked TypedefTypes for error reporting.
      for (int i = uncheckedTypedefTypeCount;
          i < library.uncheckedTypedefTypes.length;
          ++i) {
        // TODO(johnniwinther): Pass the uri/offset through the build methods
        // to avoid this.
        library.uncheckedTypedefTypes[i]
          ..fileUri ??= fileUri
          ..offset ??= charOffset;
      }
      return builtType;
    } else {
      return declarationBuildType(library, forTypeLiteral: forTypeLiteral);
    }
  }

  @override
  Supertype? buildSupertype(
      LibraryBuilder library, int charOffset, Uri fileUri) {
    TypeDeclarationBuilder declaration = this.declaration!;
    if (declaration is ClassBuilder) {
      if (declaration.isNullClass && !library.mayImplementRestrictedTypes) {
        library.addProblem(
            templateExtendingRestricted.withArguments(declaration.name),
            charOffset,
            noLength,
            fileUri);
      }
      return declaration.buildSupertype(library, arguments);
    } else if (declaration is TypeAliasBuilder) {
      TypeAliasBuilder aliasBuilder = declaration;
      DartType type = build(library);
      if (type is InterfaceType && type.nullability != Nullability.nullable) {
        return new Supertype(type.classNode, type.typeArguments);
      } else if (type is NullType) {
        // Even though Null is disallowed as a supertype, ClassHierarchyBuilder
        // still expects it to be built to the respective InterfaceType
        // referencing the deprecated class.
        // TODO(dmitryas): Remove the dependency on the deprecated Null class
        // from ClassHierarchyBuilder.
        TypeDeclarationBuilder? unaliasedDeclaration = this.declaration;
        // The following code assumes that the declaration is a TypeAliasBuilder
        // that through a chain of other TypeAliasBuilders (possibly, the chain
        // length is 0) references a ClassBuilder of the Null class.  Otherwise,
        // it won't produce the NullType on the output.
        while (unaliasedDeclaration is TypeAliasBuilder) {
          unaliasedDeclaration = unaliasedDeclaration.type?.declaration;
          assert(unaliasedDeclaration != null);
        }
        assert(unaliasedDeclaration is ClassBuilder &&
            unaliasedDeclaration.name == "Null");
        return new Supertype(
            (unaliasedDeclaration as ClassBuilder).cls, const <DartType>[]);
      } else if (type is FutureOrType) {
        // Even though FutureOr is disallowed as a supertype,
        // ClassHierarchyBuilder still expects it to be built to the respective
        // InterfaceType referencing the deprecated class.  In contrast with
        // Null, it doesn't surface as an error due to FutureOr class not having
        // any inheritable members.
        // TODO(dmitryas): Remove the dependency on the deprecated FutureOr
        // class from ClassHierarchyBuilder.
        TypeDeclarationBuilder? unaliasedDeclaration = this.declaration;
        // The following code assumes that the declaration is a TypeAliasBuilder
        // that through a chain of other TypeAliasBuilders (possibly, the chain
        // length is 0) references a ClassBuilder of the FutureOr class.
        // Otherwise, it won't produce the FutureOrType on the output.
        while (unaliasedDeclaration is TypeAliasBuilder) {
          unaliasedDeclaration = unaliasedDeclaration.type?.declaration;
          assert(unaliasedDeclaration != null);
        }
        assert(unaliasedDeclaration is ClassBuilder &&
            unaliasedDeclaration.name == "FutureOr");
        return new Supertype((unaliasedDeclaration as ClassBuilder).cls,
            <DartType>[type.typeArgument]);
      }
      return handleInvalidAliasedSupertype(
          library, charOffset, fileUri, aliasBuilder, type);
    } else if (declaration is InvalidTypeDeclarationBuilder) {
      library.addProblem(
          declaration.message.messageObject,
          declaration.message.charOffset,
          declaration.message.length,
          declaration.message.uri,
          severity: Severity.error);
      return null;
    }
    return handleInvalidSupertype(library, charOffset, fileUri);
  }

  @override
  Supertype? buildMixedInType(
      LibraryBuilder library, int charOffset, Uri fileUri) {
    TypeDeclarationBuilder declaration = this.declaration!;
    if (declaration is ClassBuilder) {
      return declaration.buildMixedInType(library, arguments);
    } else if (declaration is TypeAliasBuilder) {
      TypeAliasBuilder aliasBuilder = declaration;
      DartType type = build(library);
      if (type is InterfaceType && type.nullability != Nullability.nullable) {
        return new Supertype(type.classNode, type.typeArguments);
      }
      return handleInvalidAliasedSupertype(
          library, charOffset, fileUri, aliasBuilder, type);
    } else if (declaration is InvalidTypeDeclarationBuilder) {
      library.addProblem(
          declaration.message.messageObject,
          declaration.message.charOffset,
          declaration.message.length,
          declaration.message.uri,
          severity: Severity.error);
      return null;
    }
    return handleInvalidSupertype(library, charOffset, fileUri);
  }

  @override
  TypeBuilder subst(Map<TypeVariableBuilder, TypeBuilder> substitution) {
    TypeBuilder? result = substitution[declaration];
    if (result != null) {
      assert(declaration is TypeVariableBuilder);
      return result;
    } else if (this.arguments != null) {
      List<TypeBuilder>? arguments;
      int i = 0;
      for (TypeBuilder argument in this.arguments!) {
        TypeBuilder type = argument.subst(substitution);
        if (type != argument) {
          arguments ??= this.arguments!.toList();
          arguments[i] = type;
        }
        i++;
      }
      if (arguments != null) {
        NamedTypeBuilder result = new NamedTypeBuilder(
            name, nullabilityBuilder, arguments, fileUri, charOffset,
            instanceTypeVariableAccess: instanceTypeVariableAccess);
        if (declaration != null) {
          result.bind(declaration!);
        } else {
          throw new UnsupportedError("Unbound type in substitution: $result.");
        }
        return result;
      }
    }
    return this;
  }

  @override
  NamedTypeBuilder clone(
      List<NamedTypeBuilder> newTypes,
      SourceLibraryBuilder contextLibrary,
      TypeParameterScopeBuilder contextDeclaration) {
    List<TypeBuilder>? clonedArguments;
    if (arguments != null) {
      clonedArguments =
          new List<TypeBuilder>.generate(arguments!.length, (int i) {
        return arguments![i]
            .clone(newTypes, contextLibrary, contextDeclaration);
      }, growable: false);
    }
    NamedTypeBuilder newType = new NamedTypeBuilder(
        name, nullabilityBuilder, clonedArguments, fileUri, charOffset,
        instanceTypeVariableAccess: instanceTypeVariableAccess);
    if (declaration is BuiltinTypeDeclarationBuilder) {
      newType.declaration = declaration;
    } else {
      newTypes.add(newType);
    }
    return newType;
  }

  @override
  NamedTypeBuilder withNullabilityBuilder(
      NullabilityBuilder nullabilityBuilder) {
    return new NamedTypeBuilder(
        name, nullabilityBuilder, arguments, fileUri, charOffset,
        instanceTypeVariableAccess: instanceTypeVariableAccess)
      ..bind(declaration!);
  }
}
