// 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/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/summary2/ast_resolver.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linking_node_scope.dart';

class DefaultValueResolver {
  final Linker _linker;
  final LibraryElementImpl _libraryElement;
  final TypeSystemImpl _typeSystem;

  late CompilationUnitElementImpl _unitElement;
  ClassElement? _classElement;
  late ExecutableElement _executableElement;
  late Scope _scope;

  DefaultValueResolver(this._linker, this._libraryElement)
      : _typeSystem = _libraryElement.typeSystem;

  void resolve() {
    for (var unit in _libraryElement.units) {
      _unitElement = unit as CompilationUnitElementImpl;

      for (var extensionElement in unit.extensions) {
        _extension(extensionElement);
      }

      for (var classElement in unit.mixins) {
        _class(classElement);
      }

      for (var classElement in unit.types) {
        _class(classElement);
      }

      for (var element in unit.functions) {
        _function(element);
      }
    }
  }

  void _class(ClassElement classElement) {
    _classElement = classElement;

    for (var element in classElement.constructors) {
      _constructor(element as ConstructorElementImpl);
    }

    for (var element in classElement.methods) {
      _setScopeFromElement(element);
      _method(element as MethodElementImpl);
    }

    _classElement = null;
  }

  void _constructor(ConstructorElementImpl element) {
    if (element.isSynthetic) return;

    _executableElement = element;
    _setScopeFromElement(element);

    _parameters(element.parameters);
  }

  DefaultFormalParameter? _defaultParameter(ParameterElementImpl element) {
    var node = _linker.getLinkingNode(element);
    if (node is DefaultFormalParameter && node.defaultValue != null) {
      return node;
    } else {
      return null;
    }
  }

  void _extension(ExtensionElement extensionElement) {
    for (var element in extensionElement.methods) {
      _setScopeFromElement(element);
      _method(element as MethodElementImpl);
    }
  }

  void _function(FunctionElement element) {
    _executableElement = element;
    _setScopeFromElement(element);

    _parameters(element.parameters);
  }

  void _method(MethodElementImpl element) {
    _executableElement = element;
    _setScopeFromElement(element);

    _parameters(element.parameters);
  }

  void _parameter(ParameterElementImpl parameter) {
    // If a function typed parameter, process nested parameters.
    for (var localParameter in parameter.parameters) {
      _parameter(localParameter as ParameterElementImpl);
    }

    var node = _defaultParameter(parameter);
    if (node == null) return;

    var contextType = _typeSystem.eliminateTypeVariables(parameter.type);

    var astResolver = AstResolver(
        _linker, _unitElement, _scope, node.defaultValue!,
        enclosingClassElement: _classElement,
        enclosingExecutableElement: _executableElement);
    astResolver.resolveExpression(() => node.defaultValue!,
        contextType: contextType);
  }

  void _parameters(List<ParameterElement> parameters) {
    for (var parameter in parameters) {
      _parameter(parameter as ParameterElementImpl);
    }
  }

  void _setScopeFromElement(Element element) {
    var node = _linker.getLinkingNode(element)!;
    _scope = LinkingNodeContext.get(node).scope;
  }
}
