// 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/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/element/element.dart';
import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/dart/element/type_visitor.dart';
import 'package:analyzer/src/summary2/function_type_builder.dart';
import 'package:analyzer/src/summary2/named_type_builder.dart';

/// Generates a fresh copy of the given type parameters, with their bounds
/// substituted to reference the new parameters.
///
/// The returned object contains the fresh type parameter list as well as a
/// mapping to be used for replacing other types to use the new type parameters.
FreshTypeParameters getFreshTypeParameters(
    List<TypeParameterElement> typeParameters) {
  var freshParameters = List<TypeParameterElementImpl>.generate(
    typeParameters.length,
    (i) => TypeParameterElementImpl(typeParameters[i].name, -1),
    growable: true,
  );

  var map = <TypeParameterElement, DartType>{};
  for (int i = 0; i < typeParameters.length; ++i) {
    map[typeParameters[i]] = TypeParameterTypeImpl(
      element: freshParameters[i],
      nullabilitySuffix: NullabilitySuffix.none,
    );
  }

  var substitution = Substitution.fromMap(map);

  for (int i = 0; i < typeParameters.length; ++i) {
    // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
    // variance is added to the interface.
    var typeParameter = typeParameters[i] as TypeParameterElementImpl;
    if (!typeParameter.isLegacyCovariant) {
      freshParameters[i].variance = typeParameter.variance;
    }

    var bound = typeParameter.bound;
    if (bound != null) {
      var newBound = substitution.substituteType(bound);
      freshParameters[i].bound = newBound;
    }
  }

  return FreshTypeParameters(freshParameters, substitution);
}

/// Given a generic function [type] of a class member (so that it does not
/// carry its element and type arguments), substitute its type parameters with
/// the [newTypeParameters] in the formal parameters and return type.
FunctionType replaceTypeParameters(
  FunctionTypeImpl type,
  List<TypeParameterElement> newTypeParameters,
) {
  assert(newTypeParameters.length == type.typeFormals.length);
  if (newTypeParameters.isEmpty) {
    return type;
  }

  var typeArguments = newTypeParameters
      .map((e) => e.instantiate(nullabilitySuffix: NullabilitySuffix.none))
      .toList();
  var substitution = Substitution.fromPairs(type.typeFormals, typeArguments);

  ParameterElement transformParameter(ParameterElement p) {
    var type = substitution.substituteType(p.type);
    return p.copyWith(type: type);
  }

  return FunctionTypeImpl(
    typeFormals: newTypeParameters,
    parameters: type.parameters.map(transformParameter).toList(),
    returnType: substitution.substituteType(type.returnType),
    nullabilitySuffix: type.nullabilitySuffix,
  );
}

/// Returns a type where all occurrences of the given type parameters have been
/// replaced with the corresponding types.
///
/// This will copy only the sub-terms of [type] that contain substituted
/// variables; all other [DartType] objects will be reused.
///
/// In particular, if no type parameters were substituted, this is guaranteed
/// to return the [type] instance (not a copy), so the caller may use
/// [identical] to efficiently check if a distinct type was created.
DartType substitute(
  DartType type,
  Map<TypeParameterElement, DartType> substitution,
) {
  if (substitution.isEmpty) {
    return type;
  }
  return Substitution.fromMap(substitution).substituteType(type);
}

///  1. Substituting T=X! into T! yields X!
///  2. Substituting T=X* into T! yields X*
///  3. Substituting T=X? into T! yields X?
///  4. Substituting T=X! into T* yields X*
///  5. Substituting T=X* into T* yields X*
///  6. Substituting T=X? into T* yields X?
///  7. Substituting T=X! into T? yields X?
///  8. Substituting T=X* into T? yields X?
///  9. Substituting T=X? into T? yields X?
NullabilitySuffix uniteNullabilities(NullabilitySuffix a, NullabilitySuffix b) {
  if (a == NullabilitySuffix.question || b == NullabilitySuffix.question) {
    return NullabilitySuffix.question;
  }
  if (a == NullabilitySuffix.star || b == NullabilitySuffix.star) {
    return NullabilitySuffix.star;
  }
  return NullabilitySuffix.none;
}

class FreshTypeParameters {
  final List<TypeParameterElement> freshTypeParameters;
  final Substitution substitution;

  FreshTypeParameters(this.freshTypeParameters, this.substitution);

  FunctionType applyToFunctionType(FunctionType type) {
    return FunctionTypeImpl(
      typeFormals: freshTypeParameters,
      parameters: type.parameters.map((parameter) {
        var type = substitute(parameter.type);
        return parameter.copyWith(type: type);
      }).toList(),
      returnType: substitute(type.returnType),
      nullabilitySuffix: type.nullabilitySuffix,
    );
  }

  DartType substitute(DartType type) => substitution.substituteType(type);
}

/// Substitution that is based on the [map].
abstract class MapSubstitution extends Substitution {
  const MapSubstitution();

  Map<TypeParameterElement, DartType> get map;
}

abstract class Substitution {
  static const MapSubstitution empty = _NullSubstitution.instance;

  const Substitution();

  DartType? getSubstitute(TypeParameterElement parameter, bool upperBound);

  DartType substituteType(DartType type, {bool contravariant = false}) {
    var visitor = _TopSubstitutor(this, contravariant);
    return type.accept(visitor);
  }

  /// Substitutes both variables from [first] and [second], favoring those from
  /// [first] if they overlap.
  ///
  /// Neither substitution is applied to the results of the other, so this does
  /// *not* correspond to a sequence of two substitutions. For example,
  /// combining `{T -> List<G>}` with `{G -> String}` does not correspond to
  /// `{T -> List<String>}` because the result from substituting `T` is not
  /// searched for occurrences of `G`.
  static Substitution combine(Substitution first, Substitution second) {
    if (first == _NullSubstitution.instance) return second;
    if (second == _NullSubstitution.instance) return first;
    return _CombinedSubstitution(first, second);
  }

  /// Substitutes the type parameters on the class of [type] with the
  /// type arguments provided in [type].
  static MapSubstitution fromInterfaceType(InterfaceType type) {
    if (type.typeArguments.isEmpty) {
      return _NullSubstitution.instance;
    }
    return fromPairs(type.element.typeParameters, type.typeArguments);
  }

  /// Substitutes each parameter to the type it maps to in [map].
  static MapSubstitution fromMap(Map<TypeParameterElement, DartType> map) {
    if (map.isEmpty) {
      return _NullSubstitution.instance;
    }
    return _MapSubstitution(map);
  }

  /// Substitutes the Nth parameter in [parameters] with the Nth type in
  /// [types].
  static MapSubstitution fromPairs(
    List<TypeParameterElement> parameters,
    List<DartType> types,
  ) {
    assert(parameters.length == types.length);
    if (parameters.isEmpty) {
      return _NullSubstitution.instance;
    }
    return fromMap(
      Map<TypeParameterElement, DartType>.fromIterables(
        parameters,
        types,
      ),
    );
  }

  /// Substitutes all occurrences of the given type parameters with the
  /// corresponding upper or lower bound, depending on the variance of the
  /// context where it occurs.
  ///
  /// For example the type `(T) => T` with the bounds `bottom <: T <: num`
  /// becomes `(bottom) => num` (in this example, `num` is the upper bound,
  /// and `bottom` is the lower bound).
  ///
  /// This is a way to obtain an upper bound for a type while eliminating all
  /// references to certain type variables.
  static Substitution fromUpperAndLowerBounds(
    Map<TypeParameterElement, DartType> upper,
    Map<TypeParameterElement, DartType> lower,
  ) {
    if (upper.isEmpty && lower.isEmpty) {
      return _NullSubstitution.instance;
    }
    return _UpperLowerBoundsSubstitution(upper, lower);
  }
}

class _CombinedSubstitution extends Substitution {
  final Substitution first;
  final Substitution second;

  _CombinedSubstitution(this.first, this.second);

  @override
  DartType? getSubstitute(TypeParameterElement parameter, bool upperBound) {
    return first.getSubstitute(parameter, upperBound) ??
        second.getSubstitute(parameter, upperBound);
  }
}

class _FreshTypeParametersSubstitutor extends _TypeSubstitutor {
  final Map<TypeParameterElement, DartType> substitution = {};

  _FreshTypeParametersSubstitutor(_TypeSubstitutor outer) : super(outer);

  @override
  List<TypeParameterElement> freshTypeParameters(
      List<TypeParameterElement> elements) {
    if (elements.isEmpty) {
      return const <TypeParameterElement>[];
    }

    var freshElements = <TypeParameterElement>[];
    for (var i = 0; i < elements.length; i++) {
      // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
      // variance is added to the interface.
      var element = elements[i] as TypeParameterElementImpl;
      var freshElement = TypeParameterElementImpl(element.name, -1);
      freshElements.add(freshElement);
      var freshType = freshElement.instantiate(
        nullabilitySuffix: NullabilitySuffix.none,
      );
      substitution[element] = freshType;

      if (!element.isLegacyCovariant) {
        freshElement.variance = element.variance;
      }
    }

    for (var i = 0; i < freshElements.length; i++) {
      var element = elements[i];
      var bound = element.bound;
      if (bound != null) {
        var freshElement = freshElements[i] as TypeParameterElementImpl;
        freshElement.bound = bound.accept(this);
      }
    }

    return freshElements;
  }

  @override
  DartType? lookup(TypeParameterElement parameter, bool upperBound) {
    return substitution[parameter];
  }
}

class _MapSubstitution extends MapSubstitution {
  @override
  final Map<TypeParameterElement, DartType> map;

  _MapSubstitution(this.map);

  @override
  DartType? getSubstitute(TypeParameterElement parameter, bool upperBound) {
    return map[parameter];
  }

  @override
  String toString() => '_MapSubstitution($map)';
}

class _NullSubstitution extends MapSubstitution {
  static const _NullSubstitution instance = _NullSubstitution();

  const _NullSubstitution();

  @override
  Map<TypeParameterElement, DartType> get map => const {};

  @override
  DartType getSubstitute(TypeParameterElement parameter, bool upperBound) {
    return TypeParameterTypeImpl(
      element: parameter,
      nullabilitySuffix: NullabilitySuffix.star,
    );
  }

  @override
  DartType substituteType(DartType type, {bool contravariant = false}) => type;

  @override
  String toString() => "Substitution.empty";
}

class _TopSubstitutor extends _TypeSubstitutor {
  final Substitution substitution;

  _TopSubstitutor(this.substitution, bool contravariant) : super(null) {
    if (contravariant) {
      invertVariance();
    }
  }

  @override
  List<TypeParameterElement> freshTypeParameters(
      List<TypeParameterElement> parameters) {
    throw 'Create a fresh environment first';
  }

  @override
  DartType? lookup(TypeParameterElement parameter, bool upperBound) {
    return substitution.getSubstitute(parameter, upperBound);
  }
}

abstract class _TypeSubstitutor
    implements
        TypeVisitor<DartType>,
        InferenceTypeVisitor<DartType>,
        LinkingTypeVisitor<DartType> {
  final _TypeSubstitutor? outer;
  bool covariantContext = true;

  /// The number of times a variable from this environment has been used in
  /// a substitution.
  ///
  /// There is a strict requirement that we must return the same instance for
  /// types that were not altered by the substitution.  This counter lets us
  /// check quickly if anything happened in a substitution.
  int useCounter = 0;

  _TypeSubstitutor(this.outer) {
    covariantContext = outer == null ? true : outer!.covariantContext;
  }

  void bumpCountersUntil(_TypeSubstitutor target) {
    var substitutor = this;
    while (substitutor != target) {
      substitutor.useCounter++;
      substitutor = substitutor.outer!;
    }
    target.useCounter++;
  }

  List<TypeParameterElement> freshTypeParameters(
      List<TypeParameterElement> elements);

  DartType? getSubstitute(TypeParameterElement parameter) {
    _TypeSubstitutor? environment = this;
    while (environment != null) {
      var replacement = environment.lookup(parameter, covariantContext);
      if (replacement != null) {
        bumpCountersUntil(environment);
        return replacement;
      }
      environment = environment.outer;
    }
    return null;
  }

  void invertVariance() {
    covariantContext = !covariantContext;
  }

  DartType? lookup(TypeParameterElement parameter, bool upperBound);

  _FreshTypeParametersSubstitutor newInnerEnvironment() {
    return _FreshTypeParametersSubstitutor(this);
  }

  @override
  DartType visitDynamicType(DynamicType type) => type;

  @override
  DartType visitFunctionType(FunctionType type) {
    // This is a bit tricky because we have to generate fresh type parameters
    // in order to change the bounds.  At the same time, if the function type
    // was unaltered, we have to return the [type] object (not a copy!).
    // Substituting a type for a fresh type variable should not be confused
    // with a "real" substitution.
    //
    // Create an inner environment to generate fresh type parameters.  The use
    // counter on the inner environment tells if the fresh type parameters have
    // any uses, but does not tell if the resulting function type is distinct.
    // Our own use counter will get incremented if something from our
    // environment has been used inside the function.
    int before = useCounter;

    var inner = this;
    var typeFormals = type.typeFormals;
    if (typeFormals.isNotEmpty) {
      inner = newInnerEnvironment();
      typeFormals = inner.freshTypeParameters(typeFormals);
    }

    // Invert the variance when translating parameters.
    inner.invertVariance();

    var parameters = type.parameters.map((parameter) {
      var type = parameter.type.accept(inner);
      return parameter.copyWith(type: type);
    }).toList();

    inner.invertVariance();

    var returnType = type.returnType.accept(inner);

    var alias = type.alias;
    var newAlias = alias != null
        ? InstantiatedTypeAliasElementImpl(
            element: alias.element,
            typeArguments: _mapList(alias.typeArguments),
          )
        : null;

    if (useCounter == before) return type;

    return FunctionTypeImpl(
      typeFormals: typeFormals,
      parameters: parameters,
      returnType: returnType,
      nullabilitySuffix: type.nullabilitySuffix,
      alias: newAlias,
    );
  }

  @override
  DartType visitFunctionTypeBuilder(FunctionTypeBuilder type) {
    // This is a bit tricky because we have to generate fresh type parameters
    // in order to change the bounds.  At the same time, if the function type
    // was unaltered, we have to return the [type] object (not a copy!).
    // Substituting a type for a fresh type variable should not be confused
    // with a "real" substitution.
    //
    // Create an inner environment to generate fresh type parameters.  The use
    // counter on the inner environment tells if the fresh type parameters have
    // any uses, but does not tell if the resulting function type is distinct.
    // Our own use counter will get incremented if something from our
    // environment has been used inside the function.
    int before = useCounter;

    var inner = this;
    var typeFormals = type.typeFormals;
    if (typeFormals.isNotEmpty) {
      inner = newInnerEnvironment();
      typeFormals = inner.freshTypeParameters(typeFormals);
    }

    // Invert the variance when translating parameters.
    inner.invertVariance();

    var parameters = type.parameters.map((parameter) {
      var type = parameter.type.accept(inner);
      return parameter.copyWith(type: type);
    }).toList();

    inner.invertVariance();

    var returnType = type.returnType.accept(inner);

    if (useCounter == before) return type;

    return FunctionTypeBuilder(
      typeFormals,
      parameters,
      returnType,
      type.nullabilitySuffix,
    );
  }

  @override
  DartType visitInterfaceType(InterfaceType type) {
    if (type.typeArguments.isEmpty) {
      return type;
    }

    int before = useCounter;
    var typeArguments = _mapList(type.typeArguments);
    if (useCounter == before) {
      return type;
    }

    return InterfaceTypeImpl(
      element: type.element,
      typeArguments: typeArguments,
      nullabilitySuffix: type.nullabilitySuffix,
    );
  }

  @override
  DartType visitNamedTypeBuilder(NamedTypeBuilder type) {
    if (type.arguments.isEmpty) {
      return type;
    }

    int before = useCounter;
    var arguments = _mapList(type.arguments);
    if (useCounter == before) {
      return type;
    }

    return NamedTypeBuilder(
      type.linker,
      type.typeSystem,
      type.element,
      arguments,
      type.nullabilitySuffix,
    );
  }

  @override
  DartType visitNeverType(NeverType type) => type;

  @override
  DartType visitTypeParameterType(TypeParameterType type) {
    var argument = getSubstitute(type.element);
    if (argument == null) {
      return type;
    }

    var parameterSuffix = type.nullabilitySuffix;
    var argumentSuffix = argument.nullabilitySuffix;
    var nullability = uniteNullabilities(parameterSuffix, argumentSuffix);
    return (argument as TypeImpl).withNullability(nullability);
  }

  @override
  DartType visitUnknownInferredType(UnknownInferredType type) => type;

  @override
  DartType visitVoidType(VoidType type) => type;

  List<DartType> _mapList(List<DartType> types) {
    return types.map((e) => e.accept(this)).toList();
  }
}

class _UpperLowerBoundsSubstitution extends Substitution {
  final Map<TypeParameterElement, DartType> upper;
  final Map<TypeParameterElement, DartType> lower;

  _UpperLowerBoundsSubstitution(this.upper, this.lower);

  @override
  DartType? getSubstitute(TypeParameterElement parameter, bool upperBound) {
    return upperBound ? upper[parameter] : lower[parameter];
  }

  @override
  String toString() => '_UpperLowerBoundsSubstitution($upper, $lower)';
}
