// Copyright (c) 2018, 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 'dart:math';

import 'package:kernel/ast.dart';

/// Class that holds the covariant and generic-covariant-impl information for
/// a member.
// TODO(johnniwinther): Cache this in ClassMember.
// TODO(johnniwinther): Maybe compact initial positional masks into a single
//  int.
class Covariance {
  static const int GenericCovariantImpl = 1;
  static const int Covariant = 2;

  /// Returns the covariance mask for [parameter].
  static int covarianceFromParameter(VariableDeclaration parameter) =>
      (parameter.isCovariantByDeclaration ? Covariant : 0) |
      (parameter.isCovariantByClass ? GenericCovariantImpl : 0);

  /// Returns the covariance mask for [field].
  static int covarianceFromField(Field field) =>
      (field.isCovariantByDeclaration ? Covariant : 0) |
      (field.isCovariantByClass ? GenericCovariantImpl : 0);

  /// Applies the [covariance] mask to [parameter].
  static void covarianceToParameter(
      int covariance, VariableDeclaration parameter) {
    if ((covariance & Covariant) != 0) {
      parameter.isCovariantByDeclaration = true;
    }
    if ((covariance & GenericCovariantImpl) != 0) {
      parameter.isCovariantByClass = true;
    }
  }

  /// Applies the [covariance] mask to parameter.
  static void covarianceToField(int covariance, Field field) {
    if ((covariance & Covariant) != 0) {
      field.isCovariantByDeclaration = true;
    }
    if ((covariance & GenericCovariantImpl) != 0) {
      field.isCovariantByClass = true;
    }
  }

  /// The covariance mask for the positional parameters.
  ///
  /// If no positional parameters have covariance, this is `null`.
  final List<int>? _positionalParameters;

  /// The covariance mask for the named parameters with name covariance.
  ///
  /// If no named parameters have covariance, this is `null`.
  final Map<String, int>? _namedParameters;

  /// The generic-covariant-impl state for the type parameters.
  ///
  /// If no type parameters are generic-covariant-impl, this is `null`.
  final List<bool>? _typeParameters;

  Covariance.internal(
      this._positionalParameters, this._namedParameters, this._typeParameters) {
    assert(_positionalParameters == null ||
        _positionalParameters.any((element) => element != 0));
    assert(_namedParameters == null ||
        _namedParameters.values.isNotEmpty &&
            _namedParameters.values.every((element) => element != 0));
    assert(
        _typeParameters == null || _typeParameters.any((element) => element));
  }

  /// The empty covariance.
  ///
  /// This is used for all members that do not use any covariance, regardless
  /// of parameter structure.
  const Covariance.empty()
      : _positionalParameters = null,
        _namedParameters = null,
        _typeParameters = null;

  /// Computes the covariance for the setter aspect of [field].
  ///
  /// The getter aspect of a field never uses covariance.
  factory Covariance.fromField(Field field) {
    int covariance = covarianceFromField(field);
    if (covariance == 0) {
      return const Covariance.empty();
    }
    return new Covariance.internal(<int>[covariance], null, null);
  }

  /// Computes the covariance for the [setter].
  factory Covariance.fromSetter(Procedure setter) {
    int covariance =
        covarianceFromParameter(setter.function.positionalParameters.first);
    if (covariance == 0) {
      return const Covariance.empty();
    }
    return new Covariance.internal(<int>[covariance], null, null);
  }

  /// Computes the covariance for the [procedure].
  factory Covariance.fromMethod(Procedure procedure) {
    FunctionNode function = procedure.function;
    List<int>? positionalParameters;
    if (function.positionalParameters.isNotEmpty) {
      for (int index = 0;
          index < function.positionalParameters.length;
          index++) {
        int covariance =
            covarianceFromParameter(function.positionalParameters[index]);
        if (covariance != 0) {
          positionalParameters ??=
              new List<int>.filled(function.positionalParameters.length, 0);
          positionalParameters[index] = covariance;
        }
      }
    }
    Map<String, int>? namedParameters;
    if (function.namedParameters.isNotEmpty) {
      for (int index = 0; index < function.namedParameters.length; index++) {
        VariableDeclaration parameter = function.namedParameters[index];
        int covariance = covarianceFromParameter(parameter);
        if (covariance != 0) {
          namedParameters ??= {};
          namedParameters[parameter.name!] = covariance;
        }
      }
    }
    List<bool>? typeParameters;
    if (function.typeParameters.isNotEmpty) {
      for (int index = 0; index < function.typeParameters.length; index++) {
        if (function.typeParameters[index].isCovariantByClass) {
          typeParameters ??=
              new List<bool>.filled(function.typeParameters.length, false);
          typeParameters[index] = true;
        }
      }
    }
    if (positionalParameters == null &&
        namedParameters == null &&
        typeParameters == null) {
      return const Covariance.empty();
    }
    return new Covariance.internal(
        positionalParameters, namedParameters, typeParameters);
  }

  /// Computes the covariance for [member].
  ///
  /// If [forSetter] is `true`, the covariance is computed for the setter
  /// aspect of [member]. Otherwise, the covariance for the getter/method aspect
  /// of [member] is computed.
  factory Covariance.fromMember(Member member, {required bool forSetter}) {
    if (member is Procedure) {
      if (member.kind == ProcedureKind.Getter) {
        return const Covariance.empty();
      } else if (member.kind == ProcedureKind.Setter) {
        return new Covariance.fromSetter(member);
      } else {
        return new Covariance.fromMethod(member);
      }
    } else if (member is Field) {
      if (forSetter) {
        return new Covariance.fromField(member);
      } else {
        return const Covariance.empty();
      }
    } else {
      throw new UnsupportedError(
          "Unexpected member $member (${member.runtimeType})");
    }
  }

  /// Returns `true` if this is the empty covariance.
  bool get isEmpty =>
      _positionalParameters == null &&
      _namedParameters == null &&
      _typeParameters == null;

  /// Returns the covariance mask for the [index]th positional parameter.
  int getPositionalVariance(int index) {
    List<int>? positionalParameters = _positionalParameters;
    return positionalParameters != null && index < positionalParameters.length
        ? positionalParameters[index]
        : 0;
  }

  /// Returns the covariance mask for the named parameter with the [name].
  int getNamedVariance(String name) {
    Map<String, int>? namedParameters = _namedParameters;
    return namedParameters != null ? (namedParameters[name] ?? 0) : 0;
  }

  /// Returns `true` if the [index]th type parameter is generic-covariant-impl.
  bool isTypeParameterGenericCovariantImpl(int index) {
    List<bool>? typeParameters = _typeParameters;
    return typeParameters != null && index < typeParameters.length
        ? typeParameters[index]
        : false;
  }

  /// Returns the merge of this covariance with [other] in which parameters are
  /// covariant if they are covariant in either this [Covariance] or [other].
  Covariance merge(Covariance other) {
    if (identical(this, other)) return this;
    List<int>? positionalParameters;
    if (_positionalParameters == null) {
      positionalParameters = other._positionalParameters;
    } else if (other._positionalParameters == null) {
      positionalParameters = _positionalParameters;
    } else {
      positionalParameters = new List<int>.filled(
          max(_positionalParameters.length, other._positionalParameters.length),
          0);
      for (int index = 0; index < positionalParameters.length; index++) {
        positionalParameters[index] =
            getPositionalVariance(index) | other.getPositionalVariance(index);
      }
    }
    Map<String, int>? namedParameters;
    if (_namedParameters == null) {
      namedParameters = other._namedParameters;
    } else if (other._namedParameters == null) {
      namedParameters = _namedParameters;
    } else {
      namedParameters = {};
      Set<String> names = {
        ..._namedParameters.keys,
        ...other._namedParameters.keys
      };
      for (String name in names) {
        namedParameters[name] =
            getNamedVariance(name) | other.getNamedVariance(name);
      }
    }
    List<bool>? typeParameters;
    if (_typeParameters == null) {
      typeParameters = other._typeParameters;
    } else if (other._typeParameters == null) {
      // Coverage-ignore-block(suite): Not run.
      typeParameters = _typeParameters;
    } else {
      typeParameters = new List<bool>.filled(
          max(_typeParameters.length, other._typeParameters.length), false);
      for (int index = 0; index < typeParameters.length; index++) {
        typeParameters[index] = isTypeParameterGenericCovariantImpl(index) ||
            // Coverage-ignore(suite): Not run.
            other.isTypeParameterGenericCovariantImpl(index);
      }
    }
    if (positionalParameters == null &&
        namedParameters == null &&
        typeParameters == null) {
      return const Covariance.empty();
    }
    return new Covariance.internal(
        positionalParameters, namedParameters, typeParameters);
  }

  /// Update [member] to have the covariant flags set with the covariance in
  /// this [Covariance].
  ///
  /// No covariance bits are removed from [member] during this process.
  void applyCovariance(Member member) {
    if (isEmpty) return;
    if (member is Procedure) {
      FunctionNode function = member.function;
      List<int>? positionalParameters = _positionalParameters;
      if (positionalParameters != null) {
        for (int index = 0; index < positionalParameters.length; index++) {
          if (index < function.positionalParameters.length) {
            covarianceToParameter(positionalParameters[index],
                function.positionalParameters[index]);
          }
        }
      }
      if (_namedParameters != null) {
        for (VariableDeclaration parameter in function.namedParameters) {
          covarianceToParameter(getNamedVariance(parameter.name!), parameter);
        }
      }
      List<bool>? typeParameters = _typeParameters;
      if (typeParameters != null) {
        for (int index = 0; index < typeParameters.length; index++) {
          if (index < function.typeParameters.length) {
            if (typeParameters[index]) {
              function.typeParameters[index].isCovariantByClass = true;
            }
          }
        }
      }
    } else if (member is Field) {
      if (_positionalParameters != null) {
        covarianceToField(getPositionalVariance(0), member);
      }
    } else {
      throw new UnsupportedError(
          "Unexpected member $member (${member.runtimeType})");
    }
  }

  @override
  int get hashCode {
    int hash = 0;
    List<int>? positionalParameters = _positionalParameters;
    if (positionalParameters != null) {
      for (int covariance in positionalParameters) {
        hash += covariance.hashCode * 17;
      }
    }
    Map<String, int>? namedParameters = _namedParameters;
    if (namedParameters != null) {
      for (String name in namedParameters.keys) {
        hash += name.hashCode * 19 + namedParameters[name].hashCode * 23;
      }
    }
    List<bool>? typeParameters = _typeParameters;
    if (typeParameters != null) {
      for (bool covariance in typeParameters) {
        if (covariance) {
          hash += covariance.hashCode * 31;
        }
      }
    }
    return hash;
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    if (other is Covariance) {
      if (_positionalParameters != other._positionalParameters) {
        if (_positionalParameters == null ||
            other._positionalParameters == null) {
          return false;
        }
        int positionalParameterCount = max(
            _positionalParameters.length, other._positionalParameters.length);
        for (int i = 0; i < positionalParameterCount; i++) {
          if (getPositionalVariance(i) != other.getPositionalVariance(i)) {
            return false;
          }
        }
      }
      if (_namedParameters != other._namedParameters) {
        if (_namedParameters == null || other._namedParameters == null) {
          return false;
        }
        Set<String> names = {
          ..._namedParameters.keys,
          ...other._namedParameters.keys
        };
        for (String name in names) {
          if (getNamedVariance(name) != other.getNamedVariance(name)) {
            return false;
          }
        }
      }
      if (_typeParameters != other._typeParameters) {
        if (_typeParameters == null || other._typeParameters == null) {
          return false;
        }
        int typeParameterCount =
            max(_typeParameters.length, other._typeParameters.length);
        for (int i = 0; i < typeParameterCount; i++) {
          if (isTypeParameterGenericCovariantImpl(i) !=
              other.isTypeParameterGenericCovariantImpl(i)) {
            return false;
          }
        }
      }
      return true;
    }
    return false;
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    if (isEmpty) {
      sb.write('Covariance.empty()');
    } else {
      sb.write('Covariance(');
      String comma = '';
      List<int>? positionalParameters = _positionalParameters;
      if (positionalParameters != null) {
        for (int index = 0; index < positionalParameters.length; index++) {
          if (positionalParameters[index] != 0) {
            sb.write(comma);
            sb.write('$index:');
            switch (positionalParameters[index]) {
              case GenericCovariantImpl:
                sb.write('GenericCovariantImpl');
                break;
              case Covariant:
                sb.write('Covariant');
                break;
              default:
                sb.write('GenericCovariantImpl+Covariant');
                break;
            }
            comma = ',';
          }
        }
      }
      Map<String, int>? namedParameters = _namedParameters;
      if (namedParameters != null) {
        for (String name in namedParameters.keys) {
          int covariance = namedParameters[name]!;
          if (covariance != 0) {
            sb.write(comma);
            sb.write('$name:');

            switch (covariance) {
              case GenericCovariantImpl:
                sb.write('GenericCovariantImpl');
                break;
              case Covariant:
                sb.write('Covariant');
                break;
              default:
                sb.write('GenericCovariantImpl+Covariant');
                break;
            }
            comma = ',';
          }
        }
      }
      List<bool>? typeParameters = _typeParameters;
      if (typeParameters != null) {
        sb.write(comma);
        sb.write('types:');
        comma = '';
        for (int index = 0; index < typeParameters.length; index++) {
          if (typeParameters[index]) {
            sb.write(comma);
            sb.write('$index');
            comma = ',';
          }
        }
      }
      sb.write(')');
    }
    return sb.toString();
  }
}
