// Copyright (c) 2019, 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.type_builder_computer;

import 'package:_fe_analyzer_shared/src/parser/parser.dart'
    show FormalParameterKind;

import 'package:kernel/ast.dart';

import '../builder/class_builder.dart';
import '../builder/dynamic_type_declaration_builder.dart';
import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/future_or_type_declaration_builder.dart';
import '../builder/library_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/never_type_declaration_builder.dart';
import '../builder/null_type_declaration_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
import '../builder/void_type_declaration_builder.dart';

import '../kernel/utils.dart';

import '../loader.dart' show Loader;

class TypeBuilderComputer implements DartTypeVisitor<TypeBuilder> {
  final Loader loader;

  const TypeBuilderComputer(this.loader);

  @override
  TypeBuilder defaultDartType(DartType node) {
    throw "Unsupported";
  }

  @override
  TypeBuilder visitInvalidType(InvalidType node) {
    return new FixedTypeBuilder(
        node, /* fileUri = */ null, /* charOffset = */ null);
  }

  @override
  TypeBuilder visitDynamicType(DynamicType node) {
    // 'dynamic' is always nullable.
    return new NamedTypeBuilder("dynamic", const NullabilityBuilder.nullable(),
        /* arguments = */ null, /* fileUri = */ null, /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
      ..bind(new DynamicTypeDeclarationBuilder(
          const DynamicType(), loader.coreLibrary, -1));
  }

  @override
  TypeBuilder visitVoidType(VoidType node) {
    // 'void' is always nullable.
    return new NamedTypeBuilder("void", const NullabilityBuilder.nullable(),
        /* arguments = */ null, /* fileUri = */ null, /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
      ..bind(new VoidTypeDeclarationBuilder(
          const VoidType(), loader.coreLibrary, -1));
  }

  @override
  TypeBuilder visitNeverType(NeverType node) {
    return new NamedTypeBuilder(
        "Never",
        new NullabilityBuilder.fromNullability(node.nullability),
        /* arguments = */ null,
        /* fileUri = */ null,
        /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
      ..bind(new NeverTypeDeclarationBuilder(node, loader.coreLibrary, -1));
  }

  @override
  TypeBuilder visitNullType(NullType node) {
    return new NamedTypeBuilder("Null", new NullabilityBuilder.nullable(),
        /* arguments = */ null, /* fileUri = */ null, /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
      ..bind(new NullTypeDeclarationBuilder(node, loader.coreLibrary, -1));
  }

  @override
  TypeBuilder visitInterfaceType(InterfaceType node) {
    ClassBuilder cls =
        loader.computeClassBuilderFromTargetClass(node.classNode);
    List<TypeBuilder>? arguments;
    List<DartType> kernelArguments = node.typeArguments;
    if (kernelArguments.isNotEmpty) {
      arguments = new List<TypeBuilder>.generate(
          kernelArguments.length, (int i) => kernelArguments[i].accept(this),
          growable: false);
    }
    return new NamedTypeBuilder(
        cls.name,
        new NullabilityBuilder.fromNullability(node.nullability),
        arguments,
        /* fileUri = */ null,
        /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
      ..bind(cls);
  }

  @override
  TypeBuilder visitExtensionType(ExtensionType node) {
    throw "Not implemented";
  }

  @override
  TypeBuilder visitFutureOrType(FutureOrType node) {
    TypeBuilder argument = node.typeArgument.accept(this);
    return new NamedTypeBuilder(
        "FutureOr",
        new NullabilityBuilder.fromNullability(node.nullability),
        [argument],
        /* fileUri = */ null,
        /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Unexpected)
      ..bind(new FutureOrTypeDeclarationBuilder(node, loader.coreLibrary, -1));
  }

  @override
  TypeBuilder visitFunctionType(FunctionType node) {
    TypeBuilder returnType = node.returnType.accept(this);
    // We could compute the type variables here. However, the current
    // implementation of [visitTypeParameterType] is sufficient.
    List<TypeVariableBuilder>? typeVariables = null;
    List<DartType> positionalParameters = node.positionalParameters;
    List<NamedType> namedParameters = node.namedParameters;
    List<FormalParameterBuilder> formals =
        new List<FormalParameterBuilder>.filled(
            positionalParameters.length + namedParameters.length,
            dummyFormalParameterBuilder);
    for (int i = 0; i < positionalParameters.length; i++) {
      TypeBuilder type = positionalParameters[i].accept(this);
      FormalParameterKind kind = FormalParameterKind.mandatory;
      if (i >= node.requiredParameterCount) {
        kind = FormalParameterKind.optionalPositional;
      }
      formals[i] = new FormalParameterBuilder(
          /* metadata = */ null,
          /* modifiers = */ 0,
          type,
          /* name = */ '',
          /* compilationUnit = */ null,
          /* charOffset = */ TreeNode.noOffset)
        ..kind = kind;
    }
    for (int i = 0; i < namedParameters.length; i++) {
      NamedType parameter = namedParameters[i];
      TypeBuilder type = parameter.type.accept(this);
      formals[i + positionalParameters.length] = new FormalParameterBuilder(
          /* metadata = */ null,
          /* modifiers = */ 0,
          type,
          parameter.name,
          /* compilationUnit = */ null,
          /* charOffset = */ TreeNode.noOffset)
        ..kind = FormalParameterKind.optionalNamed;
    }
    return new FunctionTypeBuilder(
        returnType,
        typeVariables,
        formals,
        new NullabilityBuilder.fromNullability(node.nullability),
        /* fileUri = */ null,
        /* charOffset = */ TreeNode.noOffset);
  }

  @override
  TypeBuilder visitTypeParameterType(TypeParameterType node) {
    TypeParameter parameter = node.parameter;
    TreeNode? kernelClassOrTypeDef = parameter.parent;
    Library? kernelLibrary;
    if (kernelClassOrTypeDef is Class) {
      kernelLibrary = kernelClassOrTypeDef.enclosingLibrary;
    } else if (kernelClassOrTypeDef is Typedef) {
      kernelLibrary = kernelClassOrTypeDef.enclosingLibrary;
    }
    LibraryBuilder library =
        loader.lookupLibraryBuilder(kernelLibrary!.importUri)!;
    return new NamedTypeBuilder(
        parameter.name!,
        new NullabilityBuilder.fromNullability(node.nullability),
        /* arguments = */ null,
        /* fileUri = */ null,
        /* charOffset = */ null,
        instanceTypeVariableAccess: InstanceTypeVariableAccessState.Allowed)
      ..bind(new TypeVariableBuilder.fromKernel(parameter, library));
  }

  @override
  TypeBuilder visitTypedefType(TypedefType node) {
    throw "Not implemented";
  }
}
