// 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/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/ast_resolver.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';

class DefaultValueResolver {
  final Linker _linker;
  final LibraryBuilder _libraryBuilder;
  final TypeSystemImpl _typeSystem;

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

  void resolve() {
    var libraryElement = _libraryBuilder.element;
    var instanceElementListList = [
      libraryElement.classes,
      libraryElement.enums,
      libraryElement.extensions,
      libraryElement.extensionTypes,
      libraryElement.mixins,
    ];
    for (var instanceElementList in instanceElementListList) {
      for (var instanceElement in instanceElementList) {
        for (var method in instanceElement.methods) {
          _executableElement(
            method,
            enclosingInterfaceElement: instanceElement.tryCast(),
          );
        }
        if (instanceElement case InterfaceElementImpl interfaceElement) {
          for (var constructor in interfaceElement.constructors) {
            _executableElement(
              constructor,
              enclosingInterfaceElement: interfaceElement,
            );
          }
        }
      }
    }

    for (var topLevelFunction in libraryElement.topLevelFunctions) {
      _executableElement(topLevelFunction, enclosingInterfaceElement: null);
    }
  }

  FormalParameterImpl? _defaultParameterNode(
    FormalParameterFragmentImpl fragment,
  ) {
    if (_linker.getLinkingNode(fragment) case FormalParameterImpl node) {
      if (node.defaultClause != null) {
        return node;
      }
    }
    return null;
  }

  void _executableElement(
    ExecutableElementImpl element, {
    required InterfaceElementImpl? enclosingInterfaceElement,
  }) {
    for (var formalParameter in element.formalParameters) {
      _formalParameterElement(
        formalParameter,
        enclosingInterfaceElement: enclosingInterfaceElement,
        enclosingExecutableElement: element,
      );
    }
  }

  void _formalParameterElement(
    FormalParameterElementImpl formalParameter, {
    required InterfaceElementImpl? enclosingInterfaceElement,
    required ExecutableElementImpl enclosingExecutableElement,
  }) {
    var firstFragment = formalParameter.firstFragment;
    var firstNode = _defaultParameterNode(firstFragment);
    if (firstNode == null) {
      return;
    }

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

    var analysisOptions = _libraryBuilder.kind.file.analysisOptions;
    var astResolver = AstResolver.forLinking(
      inheritance: _linker.inheritance,
      libraryFragment: firstFragment.libraryFragment as LibraryFragmentImpl,
      nameScope: firstNode.scope!,
      analysisOptions: analysisOptions,
      enclosingClassElement: enclosingInterfaceElement,
      enclosingExecutableElement: enclosingExecutableElement,
    );
    firstFragment.constantInitializer2 = astResolver.resolveDefaultValue(
      firstNode.defaultClause!,
      contextType: contextType,
    );
    formalParameter.resetConstantInitializer();
  }
}
