// Copyright (c) 2020, 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/type.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_system.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';

/// Replace every "top" type in a covariant position with [_bottomType].
/// Replace every "bottom" type in a contravariant position with [_topType].
class ReplaceTopBottomVisitor {
  final TypeSystemImpl _typeSystem;
  final DartType _topType;
  final DartType _bottomType;

  ReplaceTopBottomVisitor._(
    this._typeSystem,
    this._topType,
    this._bottomType,
  );

  DartType process(DartType type, Variance variance) {
    if (_typeSystem.isNonNullableByDefault) {
      if (variance.isContravariant) {
        // ...replacing every occurrence in `T` of a type `S` in a contravariant
        // position where `S <: Never` by `Object?`
        if (_typeSystem.isSubtypeOf(type, NeverTypeImpl.instance)) {
          return _topType;
        }
      } else {
        // ...and every occurrence in `T` of a top type in a position which
        // is not contravariant by `Never`.
        if (_typeSystem.isTop(type)) {
          return _bottomType;
        }
      }
    } else {
      if (variance.isCovariant) {
        // ...replacing every occurrence in `T` of a top type in a covariant
        // position by `Null`
        if (_typeSystem.isTop(type)) {
          return _bottomType;
        }
      } else if (variance.isContravariant) {
        // ...and every occurrence in `T` of `Null` in a contravariant
        // position by `Object`
        if (type.isDartCoreNull) {
          return _topType;
        }
      }
    }

    if (type.aliasElement != null) {
      return _typeAliasInstantiation(type, variance);
    } else if (type is InterfaceType) {
      return _interfaceType(type, variance);
    } else if (type is FunctionType) {
      return _functionType(type, variance);
    }
    return type;
  }

  DartType _functionType(FunctionType type, Variance variance) {
    var newReturnType = process(type.returnType, variance);

    var newParameters = type.parameters.map((parameter) {
      return parameter.copyWith(
        type: process(
          parameter.type,
          variance.combine(Variance.contravariant),
        ),
      );
    }).toList();

    return FunctionTypeImpl(
      typeFormals: type.typeFormals,
      parameters: newParameters,
      returnType: newReturnType,
      nullabilitySuffix: type.nullabilitySuffix,
    );
  }

  DartType _interfaceType(InterfaceType type, Variance variance) {
    var typeParameters = type.element.typeParameters;
    if (typeParameters.isEmpty) {
      return type;
    }

    var typeArguments = type.typeArguments;
    assert(typeParameters.length == typeArguments.length);

    var newTypeArguments = <DartType>[];
    for (var i = 0; i < typeArguments.length; i++) {
      var newTypeArgument = process(typeArguments[i], variance);
      newTypeArguments.add(newTypeArgument);
    }

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

  DartType _typeAliasInstantiation(DartType type, Variance variance) {
    var aliasElement = type.aliasElement!;
    var aliasArguments = type.aliasArguments!;

    var typeParameters = aliasElement.typeParameters;
    assert(typeParameters.length == aliasArguments.length);

    var newTypeArguments = <DartType>[];
    for (var i = 0; i < typeParameters.length; i++) {
      var typeParameter = typeParameters[i] as TypeParameterElementImpl;
      newTypeArguments.add(
        process(
          aliasArguments[i],
          typeParameter.variance.combine(variance),
        ),
      );
    }

    return aliasElement.instantiate(
      typeArguments: newTypeArguments,
      nullabilitySuffix: type.nullabilitySuffix,
    );
  }

  /// Runs an instance of the visitor on the given [type] and returns the
  /// resulting type.  If the type contains no instances of Top or Bottom, the
  /// original type object is returned to avoid unnecessary allocation.
  static DartType run({
    required DartType topType,
    required DartType bottomType,
    required TypeSystemImpl typeSystem,
    required DartType type,
  }) {
    var visitor = ReplaceTopBottomVisitor._(typeSystem, topType, bottomType);
    return visitor.process(type, Variance.covariant);
  }
}
