// 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/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/summary2/function_type_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/named_type_builder.dart';
import 'package:analyzer/src/summary2/record_type_builder.dart';

class VarianceBuilder {
  final Linker _linker;
  final Set<TypeAlias> _pending = Set.identity();
  final Set<TypeAlias> _visit = Set.identity();

  VarianceBuilder(this._linker);

  void perform() {
    for (var builder in _linker.builders.values) {
      for (var linkingUnit in builder.units) {
        for (var node in linkingUnit.node.declarations) {
          if (node is FunctionTypeAlias) {
            _pending.add(node);
          } else if (node is GenericTypeAlias) {
            _pending.add(node);
          }
        }
      }
    }

    for (var builder in _linker.builders.values) {
      for (var linkingUnit in builder.units) {
        for (var node in linkingUnit.node.declarations) {
          if (node is ClassTypeAlias) {
            _typeParameters(node.typeParameters);
          } else if (node is ClassDeclaration) {
            _typeParameters(node.typeParameters);
          } else if (node is EnumDeclaration) {
            _typeParameters(node.typeParameters);
          } else if (node is FunctionTypeAlias) {
            _functionTypeAlias(node);
          } else if (node is GenericTypeAlias) {
            _genericTypeAlias(node);
          } else if (node is MixinDeclaration) {
            _typeParameters(node.typeParameters);
          }
        }
      }
    }
  }

  Variance _compute(TypeParameterElement variable, DartType? type) {
    if (type is TypeParameterType) {
      if (type.element == variable) {
        return Variance.covariant;
      } else {
        return Variance.unrelated;
      }
    } else if (type is NamedTypeBuilder) {
      var element = type.element;
      var arguments = type.arguments;
      if (element is InterfaceElement) {
        var result = Variance.unrelated;
        if (arguments.isNotEmpty) {
          var parameters = element.typeParameters;
          for (var i = 0; i < arguments.length && i < parameters.length; i++) {
            var parameter = parameters[i] as TypeParameterElementImpl;
            result = result.meet(
              parameter.variance.combine(
                _compute(variable, arguments[i]),
              ),
            );
          }
        }
        return result;
      } else if (element is TypeAliasElementImpl) {
        _typeAliasElement(element);

        var result = Variance.unrelated;

        if (arguments.isNotEmpty) {
          var parameters = element.typeParameters;
          for (var i = 0; i < arguments.length && i < parameters.length; i++) {
            var parameter = parameters[i] as TypeParameterElementImpl;
            var parameterVariance = parameter.variance;
            result = result.meet(
              parameterVariance.combine(
                _compute(variable, arguments[i]),
              ),
            );
          }
        }
        return result;
      }
    } else if (type is FunctionTypeBuilder) {
      return _computeFunctionType(
        variable,
        returnType: type.returnType,
        typeFormals: type.typeFormals,
        parameters: type.parameters,
      );
    } else if (type is RecordTypeBuilder) {
      var result = Variance.unrelated;
      for (final field in type.node.fields) {
        result = result.meet(
          _compute(variable, field.type.typeOrThrow),
        );
      }
      return result;
    }
    return Variance.unrelated;
  }

  Variance _computeFunctionType(
    TypeParameterElement variable, {
    required DartType? returnType,
    required List<TypeParameterElement>? typeFormals,
    required List<ParameterElement> parameters,
  }) {
    var result = Variance.unrelated;

    result = result.meet(
      _compute(variable, returnType),
    );

    // If [variable] is referenced in a bound at all, it makes the
    // variance of [variable] in the entire type invariant.
    if (typeFormals != null) {
      for (var parameter in typeFormals) {
        var bound = parameter.bound;
        if (bound != null && _compute(variable, bound) != Variance.unrelated) {
          result = Variance.invariant;
        }
      }
    }

    for (var parameter in parameters) {
      result = result.meet(
        Variance.contravariant.combine(
          _compute(variable, parameter.type),
        ),
      );
    }

    return result;
  }

  void _functionTypeAlias(FunctionTypeAlias node) {
    var parameterList = node.typeParameters;
    if (parameterList == null) {
      return;
    }

    // Recursion detected, recover.
    if (_visit.contains(node)) {
      for (var parameter in parameterList.typeParameters) {
        _setVariance(parameter, Variance.covariant);
      }
      return;
    }

    // Not being linked, or already linked.
    if (!_pending.remove(node)) {
      return;
    }

    _visit.add(node);
    try {
      for (var parameter in parameterList.typeParameters) {
        var variance = _computeFunctionType(
          parameter.declaredElement!,
          returnType: node.returnType?.type,
          typeFormals: null,
          parameters: FunctionTypeBuilder.getParameters(
            false,
            node.parameters,
          ),
        );
        _setVariance(parameter, variance);
      }
    } finally {
      _visit.remove(node);
    }
  }

  void _genericTypeAlias(GenericTypeAlias node) {
    var parameterList = node.typeParameters;
    if (parameterList == null) {
      return;
    }

    // Recursion detected, recover.
    if (_visit.contains(node)) {
      for (var parameter in parameterList.typeParameters) {
        _setVariance(parameter, Variance.covariant);
      }
      return;
    }

    // Not being linked, or already linked.
    if (!_pending.remove(node)) {
      return;
    }

    var type = node.type.type;

    // Not a function type, recover.
    if (type == null) {
      for (var parameter in parameterList.typeParameters) {
        _setVariance(parameter, Variance.covariant);
      }
    }

    _visit.add(node);
    try {
      for (var parameter in parameterList.typeParameters) {
        var variance = _compute(parameter.declaredElement!, type);
        _setVariance(parameter, variance);
      }
    } finally {
      _visit.remove(node);
    }
  }

  void _typeAliasElement(TypeAliasElementImpl element) {
    var node = _linker.getLinkingNode(element);
    if (node == null) {
      // Not linking.
    } else if (node is GenericTypeAlias) {
      _genericTypeAlias(node);
    } else if (node is FunctionTypeAlias) {
      _functionTypeAlias(node);
    } else {
      throw UnimplementedError('(${node.runtimeType}) $node');
    }
  }

  void _typeParameters(TypeParameterList? parameterList) {
    if (parameterList == null) {
      return;
    }

    for (var parameter in parameterList.typeParameters) {
      var parameterImpl = parameter as TypeParameterImpl;
      var varianceKeyword = parameterImpl.varianceKeyword;
      if (varianceKeyword != null) {
        var variance = Variance.fromKeywordString(varianceKeyword.lexeme);
        _setVariance(parameter, variance);
      }
    }
  }

  static void _setVariance(TypeParameter node, Variance variance) {
    var element = node.declaredElement as TypeParameterElementImpl;
    element.variance = variance;
  }
}
