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

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_visitor.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/element/type_visitor.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/type_builder.dart';

/// The type builder for a [NamedType].
class NamedTypeBuilder extends TypeBuilder {
  /// TODO(scheglov) Replace with `DartType` in `TypeAliasElementImpl`.
  static const _aliasedTypeKey = '_aliasedType';
  static DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;

  /// The linker that contains this type.
  final Linker linker;

  /// The type system of the library with the type name.
  final TypeSystemImpl typeSystem;

  @override
  final Element element;

  final List<DartType> arguments;

  @override
  final NullabilitySuffix nullabilitySuffix;

  /// The node for which this builder is created, or `null` if the builder
  /// was detached from its node, e.g. during computing default types for
  /// type parameters.
  final NamedTypeImpl? node;

  /// The actual built type, not a [TypeBuilder] anymore.
  ///
  /// When [build] is called, the type is built, stored into this field,
  /// and set for the [node].
  DartType? _type;

  NamedTypeBuilder(this.linker, this.typeSystem, this.element, this.arguments,
      this.nullabilitySuffix,
      {this.node});

  factory NamedTypeBuilder.of(
    Linker linker,
    TypeSystemImpl typeSystem,
    NamedTypeImpl node,
    Element element,
    NullabilitySuffix nullabilitySuffix,
  ) {
    List<DartType> arguments;
    var argumentList = node.typeArguments;
    if (argumentList != null) {
      arguments = argumentList.arguments.map((n) => n.typeOrThrow).toList();
    } else {
      arguments = <DartType>[];
    }

    return NamedTypeBuilder(
        linker, typeSystem, element, arguments, nullabilitySuffix,
        node: node);
  }

  /// TODO(scheglov) Only when enabled both in the element, and target?
  bool get _isNonFunctionTypeAliasesEnabled {
    return element.library!.featureSet.isEnabled(
      Feature.nonfunction_type_aliases,
    );
  }

  @override
  R accept<R>(TypeVisitor<R> visitor) {
    if (visitor is LinkingTypeVisitor<R>) {
      var visitor2 = visitor as LinkingTypeVisitor<R>;
      return visitor2.visitNamedTypeBuilder(this);
    } else {
      throw StateError('Should not happen outside linking.');
    }
  }

  @override
  DartType build() {
    if (_type != null) {
      return _type!;
    }

    final element = this.element;
    if (element is ClassElement) {
      var parameters = element.typeParameters;
      var arguments = _buildArguments(parameters);
      var type = element.instantiate(
        typeArguments: arguments,
        nullabilitySuffix: nullabilitySuffix,
      );
      type = typeSystem.toLegacyTypeIfOptOut(type) as InterfaceType;
      _type = type;
    } else if (element is TypeAliasElementImpl) {
      var aliasedType = _getAliasedType(element);
      var parameters = element.typeParameters;
      var arguments = _buildArguments(parameters);
      element.aliasedType = aliasedType;
      var type = element.instantiate(
        typeArguments: arguments,
        nullabilitySuffix: nullabilitySuffix,
      );
      type = typeSystem.toLegacyTypeIfOptOut(type);
      _type = type;
    } else if (element is NeverElementImpl) {
      if (typeSystem.isNonNullableByDefault) {
        _type = NeverTypeImpl.instance.withNullability(nullabilitySuffix);
      } else {
        _type = typeSystem.typeProvider.nullType;
      }
    } else if (element is TypeParameterElement) {
      _type = TypeParameterTypeImpl(
        element: element,
        nullabilitySuffix: nullabilitySuffix,
      );
    } else {
      _type = _dynamicType;
    }

    node?.type = _type;
    return _type!;
  }

  @override
  String toString() {
    var buffer = StringBuffer();
    buffer.write(element.displayName);
    if (arguments.isNotEmpty) {
      buffer.write('<');
      buffer.write(arguments.join(', '));
      buffer.write('>');
    }
    return buffer.toString();
  }

  @override
  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
    if (this.nullabilitySuffix == nullabilitySuffix) {
      return this;
    }

    return NamedTypeBuilder(
        linker, typeSystem, element, arguments, nullabilitySuffix,
        node: node);
  }

  DartType _buildAliasedType(TypeAnnotation? node) {
    if (_isNonFunctionTypeAliasesEnabled) {
      if (node != null) {
        return _buildType(node.typeOrThrow);
      } else {
        return _dynamicType;
      }
    } else {
      if (node is GenericFunctionType) {
        return _buildType(node.typeOrThrow);
      } else {
        return FunctionTypeImpl(
          typeFormals: const <TypeParameterElement>[],
          parameters: const <ParameterElement>[],
          returnType: _dynamicType,
          nullabilitySuffix: NullabilitySuffix.none,
        );
      }
    }
  }

  /// Build arguments that correspond to the type [parameters].
  List<DartType> _buildArguments(List<TypeParameterElement> parameters) {
    if (parameters.isEmpty) {
      return const <DartType>[];
    } else if (arguments.isNotEmpty) {
      if (arguments.length == parameters.length) {
        return List.generate(arguments.length, (index) {
          var type = arguments[index];
          return _buildType(type);
        });
      } else {
        return _listOfDynamic(parameters.length);
      }
    } else {
      return List.generate(parameters.length, (index) {
        var parameter = parameters[index] as TypeParameterElementImpl;
        var defaultType = parameter.defaultType!;
        return _buildType(defaultType);
      });
    }
  }

  DartType _buildFormalParameterType(FormalParameter node) {
    if (node is DefaultFormalParameter) {
      return _buildFormalParameterType(node.parameter);
    } else if (node is FunctionTypedFormalParameter) {
      return _buildFunctionType(
        typeParameterList: node.typeParameters,
        returnTypeNode: node.returnType,
        parameterList: node.parameters,
        hasQuestion: node.question != null,
      );
    } else if (node is SimpleFormalParameter) {
      return _buildNodeType(node.type);
    } else {
      throw UnimplementedError('(${node.runtimeType}) $node');
    }
  }

  FunctionType _buildFunctionType({
    required TypeParameterList? typeParameterList,
    required TypeAnnotation? returnTypeNode,
    required FormalParameterList parameterList,
    required bool hasQuestion,
  }) {
    var returnType = _buildNodeType(returnTypeNode);
    var typeParameters = _typeParameters(typeParameterList);
    var formalParameters = _formalParameters(parameterList);

    return FunctionTypeImpl(
      typeFormals: typeParameters,
      parameters: formalParameters,
      returnType: returnType,
      nullabilitySuffix: _getNullabilitySuffix(hasQuestion),
    );
  }

  DartType _buildNodeType(TypeAnnotation? node) {
    if (node == null) {
      return _dynamicType;
    } else {
      return _buildType(node.typeOrThrow);
    }
  }

  List<ParameterElementImpl> _formalParameters(FormalParameterList node) {
    return node.parameters.asImpl.map((parameter) {
      return ParameterElementImpl.synthetic(
        parameter.name?.lexeme ?? '',
        _buildFormalParameterType(parameter),
        parameter.kind,
      );
    }).toList();
  }

  DartType _getAliasedType(TypeAliasElementImpl element) {
    var typedefNode = linker.getLinkingNode(element);

    // If the element is not being linked, the types have already been built.
    if (typedefNode == null) {
      return element.aliasedType;
    }

    // Break a possible recursion.
    var existing = typedefNode.getProperty(_aliasedTypeKey) as DartType?;
    if (existing != null) {
      return existing;
    } else {
      _setAliasedType(typedefNode, _dynamicType);
    }

    if (typedefNode is FunctionTypeAlias) {
      var result = _buildFunctionType(
        typeParameterList: null,
        returnTypeNode: typedefNode.returnType,
        parameterList: typedefNode.parameters,
        hasQuestion: false,
      );
      _setAliasedType(typedefNode, result);
      return result;
    } else if (typedefNode is GenericTypeAlias) {
      var aliasedTypeNode = typedefNode.type;
      var aliasedType = _buildAliasedType(aliasedTypeNode);
      _setAliasedType(typedefNode, aliasedType);
      return aliasedType;
    } else {
      throw StateError('(${element.runtimeType}) $element');
    }
  }

  NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) {
    if (hasQuestion) {
      return NullabilitySuffix.question;
    } else if (typeSystem.isNonNullableByDefault) {
      return NullabilitySuffix.none;
    } else {
      return NullabilitySuffix.star;
    }
  }

  /// If the [type] is a [TypeBuilder], build it; otherwise return as is.
  static DartType _buildType(DartType type) {
    if (type is TypeBuilder) {
      return type.build();
    } else {
      return type;
    }
  }

  static List<DartType> _listOfDynamic(int length) {
    return List<DartType>.filled(length, _dynamicType);
  }

  static void _setAliasedType(AstNode node, DartType type) {
    node.setProperty(_aliasedTypeKey, type);
  }

  static List<TypeParameterElement> _typeParameters(TypeParameterList? node) {
    if (node != null) {
      return node.typeParameters
          .map<TypeParameterElement>((p) => p.declaredElement!)
          .toList();
    } else {
      return const <TypeParameterElement>[];
    }
  }
}
