// 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/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:nnbd_migration/src/nullability_node.dart';

/// Representation of a type in the code to be migrated.  In addition to
/// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s
/// indicating whether the type, and the types that compose it, are nullable.
class DecoratedType {
  /// Mapping from type parameter elements to the decorated types of those type
  /// parameters' bounds.
  ///
  /// This expando only applies to type parameters whose enclosing element is
  /// `null`.  Type parameters whose enclosing element is not `null` should be
  /// stored in [Variables._decoratedTypeParameterBounds].
  static final _decoratedTypeParameterBounds = Expando<DecoratedType>();

  final DartType type;

  final NullabilityNode node;

  /// If `this` is a function type, the [DecoratedType] of its return type.
  final DecoratedType returnType;

  /// If `this` is a function type, the [DecoratedType] of each of its
  /// positional parameters (including both required and optional positional
  /// parameters).
  final List<DecoratedType> positionalParameters;

  /// If `this` is a function type, the [DecoratedType] of each of its named
  /// parameters.
  final Map<String, DecoratedType> namedParameters;

  /// If `this` is a parameterized type, the [DecoratedType] of each of its
  /// type parameters.
  ///
  /// TODO(paulberry): how should we handle generic typedefs?
  final List<DecoratedType> typeArguments;

  /// If `this` is a function type, the [DecoratedType] of each of the bounds of
  /// its type parameters.
  final List<DecoratedType> typeFormalBounds;

  DecoratedType(this.type, this.node,
      {this.returnType,
      this.positionalParameters = const [],
      this.namedParameters = const {},
      this.typeArguments = const [],
      this.typeFormalBounds = const []}) {
    assert(() {
      assert(node != null);
      var type = this.type;
      if (type is InterfaceType) {
        assert(returnType == null);
        assert(positionalParameters.isEmpty);
        assert(namedParameters.isEmpty);
        assert(typeFormalBounds.isEmpty);
        assert(typeArguments.length == type.typeArguments.length);
        for (int i = 0; i < typeArguments.length; i++) {
          assert(typeArguments[i].type == type.typeArguments[i]);
        }
      } else if (type is FunctionType) {
        assert(typeFormalBounds.length == type.typeFormals.length);
        for (int i = 0; i < typeFormalBounds.length; i++) {
          var declaredBound = type.typeFormals[i].bound;
          if (declaredBound == null) {
            assert(typeFormalBounds[i].type.toString() == 'Object');
          } else {
            assert(typeFormalBounds[i].type == declaredBound);
          }
        }
        assert(returnType.type == type.returnType);
        int positionalParameterCount = 0;
        int namedParameterCount = 0;
        for (var parameter in type.parameters) {
          if (parameter.isNamed) {
            assert(namedParameters[parameter.name].type == parameter.type);
            namedParameterCount++;
          } else {
            assert(positionalParameters[positionalParameterCount].type ==
                parameter.type);
            positionalParameterCount++;
          }
        }
        assert(positionalParameters.length == positionalParameterCount);
        assert(namedParameters.length == namedParameterCount);
        assert(typeArguments.isEmpty);
      } else if (node is TypeParameterType) {
        assert(returnType == null);
        assert(positionalParameters.isEmpty);
        assert(namedParameters.isEmpty);
        assert(typeArguments.isEmpty);
        assert(typeFormalBounds.isEmpty);
      } else {
        assert(returnType == null);
        assert(positionalParameters.isEmpty);
        assert(namedParameters.isEmpty);
        assert(typeArguments.isEmpty);
        assert(typeFormalBounds.isEmpty);
      }
      return true;
    }());
  }

  /// Creates a decorated type corresponding to [type], with fresh nullability
  /// nodes everywhere that don't correspond to any source location.  These
  /// nodes can later be unioned with other nodes.
  factory DecoratedType.forImplicitFunction(TypeProvider typeProvider,
      FunctionType type, NullabilityNode node, NullabilityGraph graph,
      {DecoratedType returnType}) {
    var positionalParameters = <DecoratedType>[];
    var namedParameters = <String, DecoratedType>{};
    for (var parameter in type.parameters) {
      if (parameter.isPositional) {
        positionalParameters.add(
            DecoratedType.forImplicitType(typeProvider, parameter.type, graph));
      } else {
        namedParameters[parameter.name] =
            DecoratedType.forImplicitType(typeProvider, parameter.type, graph);
      }
    }
    return DecoratedType(type, node,
        typeFormalBounds: type.typeFormals
            .map((e) => DecoratedType.forImplicitType(
                typeProvider, e.bound ?? typeProvider.objectType, graph))
            .toList(),
        returnType: returnType ??
            DecoratedType.forImplicitType(typeProvider, type.returnType, graph),
        namedParameters: namedParameters,
        positionalParameters: positionalParameters);
  }

  /// Creates a DecoratedType corresponding to [type], with fresh nullability
  /// nodes everywhere that don't correspond to any source location.  These
  /// nodes can later be unioned with other nodes.
  factory DecoratedType.forImplicitType(
      TypeProvider typeProvider, DartType type, NullabilityGraph graph,
      {List<DecoratedType> typeArguments}) {
    if (type.isDynamic || type.isVoid) {
      assert(typeArguments == null);
      return DecoratedType(type, graph.always);
    } else if (type is InterfaceType) {
      assert(() {
        if (typeArguments != null) {
          assert(typeArguments.length == type.typeArguments.length);
          for (var i = 0; i < typeArguments.length; ++i) {
            assert(typeArguments[i].type == type.typeArguments[i]);
          }
        }
        return true;
      }());

      typeArguments ??= type.typeArguments
          .map((t) => DecoratedType.forImplicitType(typeProvider, t, graph))
          .toList();
      return DecoratedType(type, NullabilityNode.forInferredType(),
          typeArguments: typeArguments);
    } else if (type is FunctionType) {
      if (typeArguments != null) {
        throw "Not supported: implicit function type with explicit type arguments";
      }
      return DecoratedType.forImplicitFunction(
          typeProvider, type, NullabilityNode.forInferredType(), graph);
    } else if (type is TypeParameterType) {
      assert(typeArguments == null);
      return DecoratedType(type, NullabilityNode.forInferredType());
    } else if (type is BottomTypeImpl) {
      assert(typeArguments == null);
      return DecoratedType(type, NullabilityNode.forInferredType());
    }
    // TODO(paulberry)
    throw UnimplementedError(
        'DecoratedType.forImplicitType(${type.runtimeType})');
  }

  /// Creates a [DecoratedType] for a synthetic type parameter, to be used
  /// during comparison of generic function types.
  DecoratedType._forTypeParameterSubstitution(TypeParameterElement parameter)
      : type = TypeParameterTypeImpl(parameter),
        node = null,
        returnType = null,
        positionalParameters = const [],
        namedParameters = const {},
        typeArguments = const [],
        typeFormalBounds = const [] {
    // We'll be storing the type parameter bounds in
    // [_decoratedTypeParameterBounds] so the type parameter needs to have an
    // enclosing element of `null`.
    assert(parameter.enclosingElement == null);
  }

  /// If `this` represents an interface type, returns the substitution necessary
  /// to produce this type using the class's type as a starting point.
  /// Otherwise throws an exception.
  ///
  /// For instance, if `this` represents `List<int?1>`, returns the substitution
  /// `{T: int?1}`, where `T` is the [TypeParameterElement] for `List`'s type
  /// parameter.
  Map<TypeParameterElement, DecoratedType> get asSubstitution {
    var type = this.type;
    if (type is InterfaceType) {
      return Map<TypeParameterElement, DecoratedType>.fromIterables(
          type.element.typeParameters, typeArguments);
    } else {
      throw StateError(
          'Tried to convert a non-interface type to a substitution');
    }
  }

  /// If this type is a function type, returns its generic formal parameters.
  /// Otherwise returns `null`.
  List<TypeParameterElement> get typeFormals {
    var type = this.type;
    if (type is FunctionType) {
      return type.typeFormals;
    } else {
      return null;
    }
  }

  @override
  bool operator ==(Object other) {
    if (other is DecoratedType) {
      if (!identical(this.node, other.node)) return false;
      var thisType = this.type;
      var otherType = other.type;
      if (thisType is FunctionType && otherType is FunctionType) {
        if (thisType.normalParameterTypes.length !=
            otherType.normalParameterTypes.length) {
          return false;
        }
        if (thisType.typeFormals.length != otherType.typeFormals.length) {
          return false;
        }
        var thisReturnType = this.returnType;
        var otherReturnType = other.returnType;
        var thisPositionalParameters = this.positionalParameters;
        var otherPositionalParameters = other.positionalParameters;
        var thisNamedParameters = this.namedParameters;
        var otherNamedParameters = other.namedParameters;
        if (!_compareTypeFormalLists(
            thisType.typeFormals, otherType.typeFormals)) {
          // Create a fresh set of type variables and substitute so we can
          // compare safely.
          var thisSubstitution = <TypeParameterElement, DecoratedType>{};
          var otherSubstitution = <TypeParameterElement, DecoratedType>{};
          var newParameters = <TypeParameterElement>[];
          for (int i = 0; i < thisType.typeFormals.length; i++) {
            var newParameter = TypeParameterElementImpl.synthetic(
                thisType.typeFormals[i].name);
            newParameters.add(newParameter);
            var newParameterType =
                DecoratedType._forTypeParameterSubstitution(newParameter);
            thisSubstitution[thisType.typeFormals[i]] = newParameterType;
            otherSubstitution[otherType.typeFormals[i]] = newParameterType;
          }
          for (int i = 0; i < thisType.typeFormals.length; i++) {
            var thisBound =
                this.typeFormalBounds[i].substitute(thisSubstitution);
            var otherBound =
                other.typeFormalBounds[i].substitute(otherSubstitution);
            if (thisBound != otherBound) return false;
            recordTypeParameterBound(newParameters[i], thisBound);
          }
          // TODO(paulberry): need to substitute bounds and compare them.
          thisReturnType = thisReturnType.substitute(thisSubstitution);
          otherReturnType = otherReturnType.substitute(otherSubstitution);
          thisPositionalParameters =
              _substituteList(thisPositionalParameters, thisSubstitution);
          otherPositionalParameters =
              _substituteList(otherPositionalParameters, otherSubstitution);
          thisNamedParameters =
              _substituteMap(thisNamedParameters, thisSubstitution);
          otherNamedParameters =
              _substituteMap(otherNamedParameters, otherSubstitution);
        }
        if (thisReturnType != otherReturnType) return false;
        if (!_compareLists(
            thisPositionalParameters, otherPositionalParameters)) {
          return false;
        }
        if (!_compareMaps(thisNamedParameters, otherNamedParameters)) {
          return false;
        }
        return true;
      } else if (thisType is InterfaceType && otherType is InterfaceType) {
        if (thisType.element != otherType.element) return false;
        if (!_compareLists(this.typeArguments, other.typeArguments)) {
          return false;
        }
        return true;
      } else {
        return thisType == otherType;
      }
    }
    return false;
  }

  /// Converts one function type into another by substituting the given
  /// [argumentTypes] for the function's generic parameters.
  DecoratedType instantiate(List<DecoratedType> argumentTypes) {
    var type = this.type as FunctionType;
    var typeFormals = type.typeFormals;
    assert(argumentTypes.length == typeFormals.length);
    List<DartType> undecoratedArgumentTypes = [];
    Map<TypeParameterElement, DecoratedType> substitution = {};
    for (int i = 0; i < argumentTypes.length; i++) {
      var argumentType = argumentTypes[i];
      undecoratedArgumentTypes.add(argumentType.type);
      substitution[typeFormals[i]] = argumentType;
    }
    return _substituteFunctionAfterFormals(
        type.instantiate(undecoratedArgumentTypes), substitution);
  }

  /// Apply the given [substitution] to this type.
  ///
  /// [undecoratedResult] is the result of the substitution, as determined by
  /// the normal type system.  If not supplied, it is inferred.
  DecoratedType substitute(
      Map<TypeParameterElement, DecoratedType> substitution,
      [DartType undecoratedResult]) {
    if (substitution.isEmpty) return this;
    if (undecoratedResult == null) {
      List<DartType> argumentTypes = [];
      List<DartType> parameterTypes = [];
      for (var entry in substitution.entries) {
        argumentTypes.add(entry.value.type);
        parameterTypes.add(entry.key.type);
      }
      undecoratedResult = type.substitute2(argumentTypes, parameterTypes);
    }
    return _substitute(substitution, undecoratedResult);
  }

  @override
  String toString() {
    var trailing = node == null ? '' : node.debugSuffix;
    var type = this.type;
    if (type is TypeParameterType || type is VoidType) {
      return '$type$trailing';
    } else if (type is InterfaceType) {
      var name = type.element.name;
      var args = '';
      if (type.typeArguments.isNotEmpty) {
        args = '<${typeArguments.join(', ')}>';
      }
      return '$name$args$trailing';
    } else if (type is FunctionType) {
      String formals = '';
      if (type.typeFormals.isNotEmpty) {
        formals = '<${type.typeFormals.join(', ')}>';
      }
      List<String> paramStrings = [];
      for (int i = 0; i < positionalParameters.length; i++) {
        var prefix = '';
        if (i == type.normalParameterTypes.length) {
          prefix = '[';
        }
        paramStrings.add('$prefix${positionalParameters[i]}');
      }
      if (type.normalParameterTypes.length < positionalParameters.length) {
        paramStrings.last += ']';
      }
      if (namedParameters.isNotEmpty) {
        var prefix = '{';
        for (var entry in namedParameters.entries) {
          paramStrings.add('$prefix${entry.key}: ${entry.value}');
          prefix = '';
        }
        paramStrings.last += '}';
      }
      var args = paramStrings.join(', ');
      return '$returnType Function$formals($args)$trailing';
    } else if (type is DynamicTypeImpl) {
      return 'dynamic';
    } else if (type.isBottom) {
      return 'Never$trailing';
    } else {
      throw '$type'; // TODO(paulberry)
    }
  }

  /// Creates a shallow copy of `this`, replacing the nullability node.
  DecoratedType withNode(NullabilityNode node) => DecoratedType(type, node,
      returnType: returnType,
      positionalParameters: positionalParameters,
      namedParameters: namedParameters,
      typeArguments: typeArguments);

  /// Internal implementation of [_substitute], used as a recursion target.
  DecoratedType _substitute(
      Map<TypeParameterElement, DecoratedType> substitution,
      DartType undecoratedResult) {
    var type = this.type;
    if (type is FunctionType && undecoratedResult is FunctionType) {
      var typeFormals = type.typeFormals;
      assert(typeFormals.length == undecoratedResult.typeFormals.length);
      var newTypeFormalBounds = <DecoratedType>[];
      if (typeFormals.isNotEmpty) {
        // The analyzer sometimes allocates fresh type variables when performing
        // substitutions, so we need to reflect that in our decorations by
        // substituting to use the type variables the analyzer used.
        substitution =
            Map<TypeParameterElement, DecoratedType>.from(substitution);
        for (int i = 0; i < typeFormals.length; i++) {
          substitution[typeFormals[i]] =
              DecoratedType._forTypeParameterSubstitution(
                  undecoratedResult.typeFormals[i]);
        }
        for (int i = 0; i < typeFormalBounds.length; i++) {
          newTypeFormalBounds.add(typeFormalBounds[i]._substitute(
              substitution, typeFormals[i].bound ?? typeFormalBounds[i].type));
        }
      }
      return _substituteFunctionAfterFormals(undecoratedResult, substitution,
          newTypeFormalBounds: newTypeFormalBounds);
    } else if (type is InterfaceType && undecoratedResult is InterfaceType) {
      List<DecoratedType> newTypeArguments = [];
      for (int i = 0; i < typeArguments.length; i++) {
        newTypeArguments.add(typeArguments[i]
            .substitute(substitution, undecoratedResult.typeArguments[i]));
      }
      return DecoratedType(undecoratedResult, node,
          typeArguments: newTypeArguments);
    } else if (type is TypeParameterType) {
      var inner = substitution[type.element];
      if (inner == null) {
        return this;
      } else {
        return inner
            .withNode(NullabilityNode.forSubstitution(inner.node, node));
      }
    } else if (type.isVoid || type.isDynamic) {
      return this;
    }
    throw '$type.substitute($type | $substitution)'; // TODO(paulberry)
  }

  /// Performs the logic that is common to substitution and function type
  /// instantiation.  Namely, a decorated type is formed whose undecorated type
  /// is [undecoratedResult], and whose return type, positional parameters, and
  /// named parameters are formed by performing the given [substitution].
  DecoratedType _substituteFunctionAfterFormals(FunctionType undecoratedResult,
      Map<TypeParameterElement, DecoratedType> substitution,
      {List<DecoratedType> newTypeFormalBounds = const []}) {
    var newPositionalParameters = <DecoratedType>[];
    var numRequiredParameters = undecoratedResult.normalParameterTypes.length;
    for (int i = 0; i < positionalParameters.length; i++) {
      var undecoratedParameterType = i < numRequiredParameters
          ? undecoratedResult.normalParameterTypes[i]
          : undecoratedResult.optionalParameterTypes[i - numRequiredParameters];
      newPositionalParameters.add(positionalParameters[i]
          ._substitute(substitution, undecoratedParameterType));
    }
    var newNamedParameters = <String, DecoratedType>{};
    for (var entry in namedParameters.entries) {
      var name = entry.key;
      var undecoratedParameterType =
          undecoratedResult.namedParameterTypes[name];
      newNamedParameters[name] =
          (entry.value._substitute(substitution, undecoratedParameterType));
    }
    return DecoratedType(undecoratedResult, node,
        typeFormalBounds: newTypeFormalBounds,
        returnType:
            returnType._substitute(substitution, undecoratedResult.returnType),
        positionalParameters: newPositionalParameters,
        namedParameters: newNamedParameters);
  }

  List<DecoratedType> _substituteList(List<DecoratedType> list,
      Map<TypeParameterElement, DecoratedType> substitution) {
    return list.map((t) => t.substitute(substitution)).toList();
  }

  Map<String, DecoratedType> _substituteMap(Map<String, DecoratedType> map,
      Map<TypeParameterElement, DecoratedType> substitution) {
    var result = <String, DecoratedType>{};
    for (var entry in map.entries) {
      result[entry.key] = entry.value.substitute(substitution);
    }
    return result;
  }

  /// Retrieves the decorated bound of the given [typeParameter].
  ///
  /// [typeParameter] must have an enclosing element of `null`.  Type parameters
  /// whose enclosing element is not `null` are tracked by the [Variables]
  /// class.
  static DecoratedType decoratedTypeParameterBound(
      TypeParameterElement typeParameter) {
    assert(typeParameter.enclosingElement == null);
    return _decoratedTypeParameterBounds[typeParameter];
  }

  /// Stores he decorated bound of the given [typeParameter].
  ///
  /// [typeParameter] must have an enclosing element of `null`.  Type parameters
  /// whose enclosing element is not `null` are tracked by the [Variables]
  /// class.
  static void recordTypeParameterBound(
      TypeParameterElement typeParameter, DecoratedType bound) {
    assert(typeParameter.enclosingElement == null);
    _decoratedTypeParameterBounds[typeParameter] = bound;
  }

  static bool _compareLists(
      List<DecoratedType> list1, List<DecoratedType> list2) {
    if (identical(list1, list2)) return true;
    if (list1.length != list2.length) return false;
    for (int i = 0; i < list1.length; i++) {
      if (list1[i] != list2[i]) return false;
    }
    return true;
  }

  static bool _compareMaps(
      Map<String, DecoratedType> map1, Map<String, DecoratedType> map2) {
    if (identical(map1, map2)) return true;
    if (map1.length != map2.length) return false;
    for (var entry in map1.entries) {
      if (entry.value != map2[entry.key]) return false;
    }
    return true;
  }

  static bool _compareTypeFormalLists(List<TypeParameterElement> formals1,
      List<TypeParameterElement> formals2) {
    if (identical(formals1, formals2)) return true;
    if (formals1.length != formals2.length) return false;
    for (int i = 0; i < formals1.length; i++) {
      if (!identical(formals1[i], formals2[i])) return false;
    }
    return true;
  }
}
