// 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';

/// The variance of a type parameter `X` in a type `T`.
class Variance {
  /// Used when `X` does not occur free in `T`.
  static const Variance unrelated = Variance._(0);

  /// Used when `X` occurs free in `T`, and `U <: V` implies `[U/X]T <: [V/X]T`.
  static const Variance covariant = Variance._(1);

  /// Used when `X` occurs free in `T`, and `U <: V` implies `[V/X]T <: [U/X]T`.
  static const Variance contravariant = Variance._(2);

  /// Used when there exists a pair `U` and `V` such that `U <: V`, but
  /// `[U/X]T` and `[V/X]T` are incomparable.
  static const Variance invariant = Variance._(3);

  /// The encoding associated with the variance.
  final int _encoding;

  /// Computes the variance of the [typeParameter] in the [type].
  factory Variance(TypeParameterElement typeParameter, DartType type) {
    if (type is TypeParameterType) {
      if (type.element2 == typeParameter) {
        return covariant;
      } else {
        return unrelated;
      }
    } else if (type is InterfaceType) {
      var result = unrelated;
      for (int i = 0; i < type.typeArguments.length; ++i) {
        var argument = type.typeArguments[i];
        var parameter = type.element2.typeParameters[i];

        // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
        // variance is added to the interface.
        var parameterVariance =
            (parameter as TypeParameterElementImpl).variance;
        result = result
            .meet(parameterVariance.combine(Variance(typeParameter, argument)));
      }
      return result;
    } else if (type is FunctionType) {
      var result = Variance(typeParameter, type.returnType);

      for (var parameter in type.typeFormals) {
        // If [parameter] is referenced in the bound at all, it makes the
        // variance of [parameter] in the entire type invariant.  The invocation
        // of [computeVariance] below is made to simply figure out if [variable]
        // occurs in the bound.
        var bound = parameter.bound;
        if (bound != null && !Variance(typeParameter, bound).isUnrelated) {
          result = invariant;
        }
      }

      for (var parameter in type.parameters) {
        result = result.meet(
          contravariant.combine(
            Variance(typeParameter, parameter.type),
          ),
        );
      }
      return result;
    }
    return unrelated;
  }

  /// Return the variance associated with the string representation of variance.
  factory Variance.fromKeywordString(String varianceString) {
    if (varianceString == "in") {
      return contravariant;
    } else if (varianceString == "inout") {
      return invariant;
    } else if (varianceString == "out") {
      return covariant;
    } else if (varianceString == "unrelated") {
      return unrelated;
    }
    throw ArgumentError('Invalid keyword string for variance: $varianceString');
  }

  /// Initialize a newly created variance to have the given [encoding].
  const Variance._(this._encoding);

  /// Return the variance with the given [encoding].
  factory Variance._fromEncoding(int encoding) {
    switch (encoding) {
      case 0:
        return unrelated;
      case 1:
        return covariant;
      case 2:
        return contravariant;
      case 3:
        return invariant;
    }
    throw ArgumentError('Invalid encoding for variance: $encoding');
  }

  /// Return `true` if this represents the case when `X` occurs free in `T`, and
  /// `U <: V` implies `[V/X]T <: [U/X]T`.
  bool get isContravariant => this == contravariant;

  /// Return `true` if this represents the case when `X` occurs free in `T`, and
  /// `U <: V` implies `[U/X]T <: [V/X]T`.
  bool get isCovariant => this == covariant;

  /// Return `true` if this represents the case when there exists a pair `U` and
  /// `V` such that `U <: V`, but `[U/X]T` and `[V/X]T` are incomparable.
  bool get isInvariant => this == invariant;

  /// Return `true` if this represents the case when `X` does not occur free in
  /// `T`.
  bool get isUnrelated => this == unrelated;

  /// Combines variances of `X` in `T` and `Y` in `S` into variance of `X` in
  /// `[Y/T]S`.
  ///
  /// Consider the following examples:
  ///
  /// * variance of `X` in `Function(X)` is contravariant, variance of `Y`
  /// in `List<Y>` is covariant, so variance of `X` in `List<Function(X)>` is
  /// contravariant;
  ///
  /// * variance of `X` in `List<X>` is covariant, variance of `Y` in
  /// `Function(Y)` is contravariant, so variance of `X` in
  /// `Function(List<X>)` is contravariant;
  ///
  /// * variance of `X` in `Function(X)` is contravariant, variance of `Y` in
  /// `Function(Y)` is contravariant, so variance of `X` in
  /// `Function(Function(X))` is covariant;
  ///
  /// * let the following be declared:
  ///
  ///     typedef F<Z> = Function();
  ///
  /// then variance of `X` in `F<X>` is unrelated, variance of `Y` in
  /// `List<Y>` is covariant, so variance of `X` in `List<F<X>>` is
  /// unrelated;
  ///
  /// * let the following be declared:
  ///
  ///     typedef G<Z> = Z Function(Z);
  ///
  /// then variance of `X` in `List<X>` is covariant, variance of `Y` in
  /// `G<Y>` is invariant, so variance of `X` in `G<List<X>>` is invariant.
  Variance combine(Variance other) {
    if (isUnrelated || other.isUnrelated) return unrelated;
    if (isInvariant || other.isInvariant) return invariant;
    return this == other ? covariant : contravariant;
  }

  /// Returns true if this variance is greater than (above) or equal to the
  /// [other] variance in the partial order induced by the variance lattice.
  ///
  ///       unrelated
  /// covariant   contravariant
  ///       invariant
  bool greaterThanOrEqual(Variance other) {
    if (isUnrelated) {
      return true;
    } else if (isCovariant) {
      return other.isCovariant || other.isInvariant;
    } else if (isContravariant) {
      return other.isContravariant || other.isInvariant;
    } else {
      assert(isInvariant);
      return other.isInvariant;
    }
  }

  /// Variance values form a lattice where unrelated is the top, invariant
  /// is the bottom, and covariant and contravariant are incomparable.
  /// [meet] calculates the meet of two elements of such lattice.  It can be
  /// used, for example, to calculate the variance of a typedef type parameter
  /// if it's encountered on the RHS of the typedef multiple times.
  ///
  ///       unrelated
  /// covariant   contravariant
  ///       invariant
  Variance meet(Variance other) =>
      Variance._fromEncoding(_encoding | other._encoding);

  /// Returns the associated keyword lexeme.
  String toKeywordString() {
    switch (this) {
      case contravariant:
        return 'in';
      case invariant:
        return 'inout';
      case covariant:
        return 'out';
      case unrelated:
        return '';
      default:
        throw ArgumentError(
            'Missing keyword lexeme representation for variance: $this');
    }
  }

  @override
  String toString() {
    switch (this) {
      case contravariant:
        return 'contravariant';
      case invariant:
        return 'invariant';
      case covariant:
        return 'covariant';
      case unrelated:
        return 'unrelated';
      default:
        throw UnimplementedError('encoding: $_encoding');
    }
  }
}
