// 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:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.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/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 FunctionTypeAliasImpl) {
            _pending.add(node);
          } else if (node is GenericTypeAliasImpl) {
            _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 ClassTypeAliasImpl) {
            _typeParameters(node.typeParameters);
          } else if (node is ClassDeclarationImpl) {
            _typeParameters(node.typeParameters);
          } else if (node is EnumDeclarationImpl) {
            _typeParameters(node.typeParameters);
          } else if (node is FunctionTypeAliasImpl) {
            _functionTypeAlias(node);
          } else if (node is GenericTypeAliasImpl) {
            _genericTypeAlias(node);
          } else if (node is MixinDeclarationImpl) {
            _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 InterfaceElementImpl) {
        var result = Variance.unrelated;
        if (arguments.isNotEmpty) {
          var typeParameters = element.typeParameters;
          for (
            var i = 0;
            i < arguments.length && i < typeParameters.length;
            i++
          ) {
            var typeParameter = typeParameters[i];
            result = result.meet(
              typeParameter.variance.combine(_compute(variable, arguments[i])),
            );
          }
        }
        return result;
      } else if (element is TypeAliasElementImpl) {
        _typeAliasElement(element);

        var result = Variance.unrelated;

        if (arguments.isNotEmpty) {
          var typeParameters = element.typeParameters;
          for (
            var i = 0;
            i < arguments.length && i < typeParameters.length;
            i++
          ) {
            var typeParameter = typeParameters[i];
            var typeParameterVariance = typeParameter.variance;
            result = result.meet(
              typeParameterVariance.combine(_compute(variable, arguments[i])),
            );
          }
        }
        return result;
      }
    } else if (type is FunctionTypeBuilder) {
      return _computeFunctionType(
        variable,
        returnType: type.returnType,
        typeParameters: type.typeParameters,
        formalParameters: type.formalParameters,
      );
    } else if (type is RecordTypeBuilder) {
      var result = Variance.unrelated;
      for (var 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>? typeParameters,
    required List<FormalParameterElement> formalParameters,
  }) {
    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 (typeParameters != null) {
      for (var typeParameter in typeParameters) {
        var bound = typeParameter.bound;
        if (bound != null && _compute(variable, bound) != Variance.unrelated) {
          result = Variance.invariant;
        }
      }
    }

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

    return result;
  }

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

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

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

    _visit.add(node);
    try {
      for (var typeParameter in parameterList.typeParameters) {
        var variance = _computeFunctionType(
          typeParameter.declaredFragment!.element,
          returnType: node.returnType?.type,
          typeParameters: null,
          formalParameters: FunctionTypeBuilder.getParameters(node.parameters),
        );
        _setVariance(typeParameter, 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 typeParameter in parameterList.typeParameters) {
        _setVariance(typeParameter, 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 typeParameter in parameterList.typeParameters) {
        _setVariance(typeParameter, Variance.covariant);
      }
    }

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

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

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

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

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