// 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/standard_ast_factory.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/ast_resolver.dart';
import 'package:analyzer/src/summary2/builder/source_library_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/reference.dart';

DartType _dynamicIfNull(DartType type) {
  if (type == null || type.isBottom || type.isDartCoreNull) {
    return DynamicTypeImpl.instance;
  }
  return type;
}

class TopLevelInference {
  final Linker linker;
  final Reference libraryRef;
  final UnitBuilder unit;
  CompilationUnitElementImpl unitElement;

  TopLevelInference(this.linker, this.libraryRef, this.unit) {
    unitElement = linker.elementFactory.elementOfReference(
      libraryRef.getChild('@unit').getChild('${unit.uri}'),
    );
  }

  void infer() {
    _inferFieldsTemporary();
    _inferConstructorFieldFormals();
  }

  void _inferConstructorFieldFormals() {
    _visitClassList((unitDeclaration) {
      var members = unitDeclaration.classOrMixinDeclaration_members;

      var fields = <String, LinkedNodeType>{};
      _visitClassFields(unitDeclaration, (field) {
        var name = unit.context.getVariableName(field);
        var type = field.variableDeclaration_type2;
        if (type == null) {
          throw StateError('Field $name should have a type.');
        }
        fields[name] = type;
      });

      for (var member in members) {
        if (member.kind == LinkedNodeKind.constructorDeclaration) {
          for (var parameter in member.constructorDeclaration_parameters
              .formalParameterList_parameters) {
            if (parameter.kind == LinkedNodeKind.fieldFormalParameter &&
                parameter.fieldFormalParameter_type2 == null) {
              var name = unit.context.getSimpleName(
                parameter.normalFormalParameter_identifier,
              );
              var type = fields[name];
              if (type == null) {
                type = LinkedNodeTypeBuilder(
                  kind: LinkedNodeTypeKind.dynamic_,
                );
              }
              parameter.fieldFormalParameter_type2 = type;
            }
          }
        }
      }
    });
  }

  void _inferFieldsTemporary() {
    var unitDeclarations = unit.node.compilationUnit_declarations;
    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
      if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
        _visitClassFields(unitDeclaration, (field) {
          var name = unit.context.getVariableName(field);
          // TODO(scheglov) Use inheritance
          if (field.variableDeclaration_type2 == null) {
            field.variableDeclaration_type2 = LinkedNodeTypeBuilder(
              kind: LinkedNodeTypeKind.dynamic_,
            );
          }
        });

        var members = unitDeclaration.classOrMixinDeclaration_members;
        for (var member in members) {
          if (member.kind == LinkedNodeKind.methodDeclaration) {
            // TODO(scheglov) Use inheritance
            if (member.methodDeclaration_returnType2 == null) {
              if (unit.context.isSetter(member)) {
                member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
                  kind: LinkedNodeTypeKind.void_,
                );
              } else {
                member.methodDeclaration_returnType2 = LinkedNodeTypeBuilder(
                  kind: LinkedNodeTypeKind.dynamic_,
                );
              }
            }
          }
        }
      } else if (unitDeclaration.kind == LinkedNodeKind.functionDeclaration) {
        if (unit.context.isSetter(unitDeclaration)) {
          unitDeclaration.functionDeclaration_returnType2 =
              LinkedNodeTypeBuilder(
            kind: LinkedNodeTypeKind.void_,
          );
        }
      } else if (unitDeclaration.kind ==
          LinkedNodeKind.topLevelVariableDeclaration) {
        var variableList =
            unitDeclaration.topLevelVariableDeclaration_variableList;
        for (var variable in variableList.variableDeclarationList_variables) {
          // TODO(scheglov) infer in the correct order
          if (variable.variableDeclaration_type2 == null ||
              unit.context.isConst(variable)) {
            _inferVariableTypeFromInitializerTemporary(variable);
          }
        }
      }
    }
  }

  void _inferVariableTypeFromInitializerTemporary(LinkedNodeBuilder node) {
    var unresolvedNode = node.variableDeclaration_initializer;

    if (unresolvedNode == null) {
      node.variableDeclaration_type2 = LinkedNodeTypeBuilder(
        kind: LinkedNodeTypeKind.dynamic_,
      );
      return;
    }

    var expression = unit.context.readInitializer(unitElement, node);
    astFactory.expressionFunctionBody(null, null, expression, null);

    // TODO(scheglov) can be shared for the whole library
    var astResolver = AstResolver(linker, libraryRef);

    var resolvedNode = astResolver.resolve(unit, expression);
    node.variableDeclaration_initializer = resolvedNode;

    if (node.variableDeclaration_type2 == null) {
      var initializerType = expression.staticType;
      initializerType = _dynamicIfNull(initializerType);

      var linkingBundleContext = linker.linkingBundleContext;
      node.variableDeclaration_type2 = linkingBundleContext.writeType(
        initializerType,
      );
    }
  }

  void _visitClassFields(
      LinkedNode class_, void Function(LinkedNodeBuilder) f) {
    var members = class_.classOrMixinDeclaration_members;

    for (var member in members) {
      if (member.kind == LinkedNodeKind.fieldDeclaration) {
        var variableList = member.fieldDeclaration_fields;
        for (var field in variableList.variableDeclarationList_variables) {
          f(field);
        }
      }
    }
  }

  void _visitClassList(void Function(LinkedNodeBuilder) f) {
    var unitDeclarations = unit.node.compilationUnit_declarations;
    for (LinkedNodeBuilder unitDeclaration in unitDeclarations) {
      if (unitDeclaration.kind == LinkedNodeKind.classDeclaration) {
        f(unitDeclaration);
      }
    }
  }
}
