// 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/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/builder.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/generated/resolver.dart';

/// This class takes a [CompilationUnitElement] lazily resynthesized from a
/// fully resolved, but partial AST (contains only APIs), and full unresolved
/// AST - and splices them into a single AST with all declaration nodes
/// fully resolved, and function bodies and variable initializers unresolved.
///
class DeclarationSplicer {
  final CompilationUnitElementImpl _unitElement;

  _ElementWalker _walker;

  DeclarationSplicer(this._unitElement);

  void splice(CompilationUnit full) {
    var partialNode = _unitElement.linkedContext.readUnitEagerly();
    _directives(full, partialNode);
    _declarations(full, partialNode);
  }

  FunctionBody _body(FunctionBody full) {
    var holder = ElementHolder();

    var elementBuilder = LocalElementBuilder(holder, null);
    full.accept(elementBuilder);

    var element = _walker.element;
    if (element is ExecutableElementImpl) {
      element.encloseElements(holder.functions);
      element.encloseElements(holder.labels);
      element.encloseElements(holder.localVariables);
    }

    return full;
  }

  void _classDeclaration(ClassDeclaration full, ClassDeclaration partial) {
    var element = _walker.getClass();
    _match(partial.name, element);
    _walk(_ElementWalker.forClass(element), () {
      _node(full.typeParameters, partial.typeParameters);
      var fullList = full.members;
      var partialList = partial.members;
      for (var i = 0; i < fullList.length; ++i) {
        _node(fullList[i], partialList[i]);
      }
    });
    _metadata(partial.metadata, element);
  }

  void _classTypeAlias(ClassTypeAlias full, ClassTypeAlias partial) {
    var element = _walker.getClass();
    _match(partial.name, element);
    _walk(_ElementWalker.forClass(element), () {
      _node(full.typeParameters, partial.typeParameters);
    });
    _metadata(partial.metadata, element);
  }

  void _constructorDeclaration(
    ConstructorDeclaration full,
    ConstructorDeclaration partial,
  ) {
    var element = _walker.getConstructor();
    _match(partial.name, element);
    (partial as ConstructorDeclarationImpl).declaredElement = element;
    _walk(_ElementWalker.forExecutable(element), () {
      _node(full.parameters, partial.parameters);
      // TODO(scheglov) Not very nice.
      if (full.initializers.isNotEmpty && partial.initializers.isEmpty) {
        partial.initializers.addAll(full.initializers);
      }
      partial.body = _body(full.body);
    });
    _metadata(partial.metadata, element);
  }

  void _declarations(CompilationUnit full, CompilationUnit partial) {
    _walk(_ElementWalker.forCompilationUnit(_unitElement), () {
      var fullList = full.declarations;
      var partialList = partial.declarations;
      for (var i = 0; i < fullList.length; ++i) {
        var partialNode = _node(fullList[i], partialList[i]);
        fullList[i] = partialNode;
      }
    });
  }

  void _directives(CompilationUnit full, CompilationUnit partial) {
    var libraryElement = _unitElement.library;
    var exportIndex = 0;
    var importIndex = 0;
    var partIndex = 0;
    for (var directive in full.directives) {
      if (directive is ExportDirective) {
        var element = libraryElement.exports[exportIndex++];
        _metadata(directive.metadata, element);
      } else if (directive is ImportDirective) {
        var element = libraryElement.imports[importIndex++];
        _metadata(directive.metadata, element);
      } else if (directive is LibraryDirective) {
        var element = libraryElement;
        _metadata(directive.metadata, element);
      } else if (directive is PartDirective) {
        var element = libraryElement.parts[partIndex++];
        _metadata(directive.metadata, element);
      }
    }
  }

  void _enumConstantDeclaration(
      EnumConstantDeclaration full, EnumConstantDeclaration partial) {
    var element = _walker.getVariable();
    _match(partial.name, element);
    _metadata(partial.metadata, element);
  }

  void _enumDeclaration(EnumDeclaration full, EnumDeclaration partial) {
    var element = _walker.getEnum();
    _match(partial.name, element);
    _walk(_ElementWalker.forClass(element), () {
      var fullList = full.constants;
      var partialList = partial.constants;
      for (var i = 0; i < fullList.length; ++i) {
        _node(fullList[i], partialList[i]);
      }
    });
    _metadata(partial.metadata, element);
  }

  void _fieldDeclaration(FieldDeclaration full, FieldDeclaration partial) {
    _node(full.fields, partial.fields);

    var first = partial.fields.variables[0];
    _metadata(partial.metadata, first.declaredElement);
  }

  void _fieldFormalParameter(
    FieldFormalParameter full,
    FieldFormalParameter partial,
  ) {
    var element = _walker.getParameter();
    _match(partial.identifier, element);
    _walk(_ElementWalker.forParameter(element), () {
      _node(full.typeParameters, partial.typeParameters);
      _node(full.parameters, partial.parameters);
    });
    _metadata(partial.metadata, element);
  }

  void _formalParameterList(
    FormalParameterList full,
    FormalParameterList partial,
  ) {
    var fullList = full.parameters;
    var partialList = partial.parameters;
    for (var i = 0; i < fullList.length; ++i) {
      _node(fullList[i], partialList[i]);
    }
  }

  void _functionDeclaration(
    FunctionDeclaration full,
    FunctionDeclaration partial,
  ) {
    var element = partial.propertyKeyword == null
        ? _walker.getFunction()
        : _walker.getAccessor();
    _match(partial.name, element);
    _walk(_ElementWalker.forExecutable(element), () {
      _node(full.functionExpression, partial.functionExpression);
    });
    (partial.functionExpression as FunctionExpressionImpl).declaredElement =
        element;
    _metadata(partial.metadata, element);
    _node(full.returnType, partial.returnType);
  }

  void _functionExpression(
    FunctionExpression full,
    FunctionExpression partial,
  ) {
    _node(full.typeParameters, partial.typeParameters);
    _node(full.parameters, partial.parameters);
    partial.body = _body(full.body);
  }

  void _functionTypeAlias(FunctionTypeAlias full, FunctionTypeAlias partial) {
    var element = _walker.getTypedef();
    _match(partial.name, element);
    _walk(_ElementWalker.forGenericTypeAlias(element), () {
      _node(full.typeParameters, partial.typeParameters);
      _node(full.parameters, partial.parameters);
    });
    _metadata(partial.metadata, element);
  }

  void _functionTypedFormalParameter(
    FunctionTypedFormalParameter full,
    FunctionTypedFormalParameter partial,
  ) {
    var element = _walker.getParameter();
    _match(partial.identifier, element);
    _walk(_ElementWalker.forParameter(element), () {
      _node(full.typeParameters, partial.typeParameters);
      _node(full.parameters, partial.parameters);
    });
    _metadata(partial.metadata, element);
  }

  void _genericFunctionType(
    GenericFunctionType full,
    GenericFunctionType partial,
  ) {
    var element = (partial as GenericFunctionTypeImpl).declaredElement;
    _walk(_ElementWalker.forGenericFunctionType(element), () {
      _node(full.returnType, partial.returnType);
      _node(full.typeParameters, partial.typeParameters);
      _node(full.parameters, partial.parameters);
    });
  }

  void _genericTypeAlias(GenericTypeAlias full, GenericTypeAlias partial) {
    var element = _walker.getTypedef();
    _match(partial.name, element);
    _walk(_ElementWalker.forGenericTypeAlias(element), () {
      _node(full.typeParameters, partial.typeParameters);
      _node(full.functionType, partial.functionType);
    });
    _metadata(partial.metadata, element);
  }

  /// Updates [node] to point to [element], after ensuring that the
  /// element has the expected name.
  E _match<E extends Element>(SimpleIdentifier node, E element) {
    // TODO(scheglov) has troubles with getter/setter.
//    if (element.name != node.name) {
//      throw new StateError(
//        'Expected an element matching `${node.name}`, got `${element.name}`',
//      );
//    }
    if (node != null) {
      node.staticElement = element;
    }
    return element;
  }

  void _methodDeclaration(MethodDeclaration full, MethodDeclaration partial) {
    var element = partial.propertyKeyword == null
        ? _walker.getFunction()
        : _walker.getAccessor();
    _match(partial.name, element);
    _walk(_ElementWalker.forExecutable(element), () {
      _node(full.typeParameters, partial.typeParameters);
      _node(full.parameters, partial.parameters);
      partial.body = _body(full.body);
    });
    _metadata(partial.metadata, element);
    _node(full.returnType, partial.returnType);
  }

  void _mixinDeclaration(MixinDeclaration full, MixinDeclaration partial) {
    var element = _walker.getMixin();
    _match(partial.name, element);
    _walk(_ElementWalker.forClass(element), () {
      _node(full.typeParameters, partial.typeParameters);
      var fullList = full.members;
      var partialList = partial.members;
      for (var i = 0; i < fullList.length; ++i) {
        _node(fullList[i], partialList[i]);
      }
    });
    _metadata(partial.metadata, element);
  }

  AstNode _node(AstNode full, AstNode partial) {
    if (full == null && partial == null) {
      return partial;
    } else if (full is ClassDeclaration && partial is ClassDeclaration) {
      _classDeclaration(full, partial);
      return partial;
    } else if (full is ClassTypeAlias && partial is ClassTypeAlias) {
      _classTypeAlias(full, partial);
      return partial;
    } else if (full is ConstructorDeclaration &&
        partial is ConstructorDeclaration) {
      _constructorDeclaration(full, partial);
      return partial;
    } else if (full is DefaultFormalParameter &&
        partial is DefaultFormalParameter) {
      _node(full.parameter, partial.parameter);
      return partial;
    } else if (full is EnumConstantDeclaration &&
        partial is EnumConstantDeclaration) {
      _enumConstantDeclaration(full, partial);
      return partial;
    } else if (full is EnumDeclaration && partial is EnumDeclaration) {
      _enumDeclaration(full, partial);
      return partial;
    } else if (full is FieldDeclaration && partial is FieldDeclaration) {
      _fieldDeclaration(full, partial);
      return partial;
    } else if (full is FieldFormalParameter &&
        partial is FieldFormalParameter) {
      _fieldFormalParameter(full, partial);
      return partial;
    } else if (full is FormalParameterList && partial is FormalParameterList) {
      _formalParameterList(full, partial);
      return partial;
    } else if (full is FunctionDeclaration && partial is FunctionDeclaration) {
      _functionDeclaration(full, partial);
      return partial;
    } else if (full is FunctionExpression && partial is FunctionExpression) {
      _functionExpression(full, partial);
      return partial;
    } else if (full is FunctionTypedFormalParameter &&
        partial is FunctionTypedFormalParameter) {
      _functionTypedFormalParameter(full, partial);
      return partial;
    } else if (full is FunctionTypeAlias && partial is FunctionTypeAlias) {
      _functionTypeAlias(full, partial);
      return partial;
    } else if (full is GenericFunctionType && partial is GenericFunctionType) {
      _genericFunctionType(full, partial);
      return partial;
    } else if (full is GenericTypeAlias && partial is GenericTypeAlias) {
      _genericTypeAlias(full, partial);
      return partial;
    } else if (full is MethodDeclaration && partial is MethodDeclaration) {
      _methodDeclaration(full, partial);
      return partial;
    } else if (full is MixinDeclaration && partial is MixinDeclaration) {
      _mixinDeclaration(full, partial);
      return partial;
    } else if (full is SimpleFormalParameter &&
        partial is SimpleFormalParameter) {
      _simpleFormalParameter(full, partial);
      return partial;
    } else if (full is TopLevelVariableDeclaration &&
        partial is TopLevelVariableDeclaration) {
      _topLevelVariableDeclaration(full, partial);
      return partial;
    } else if (full is TypeName && partial is TypeName) {
      _typeName(full, partial);
      return partial;
    } else if (full is TypeParameter && partial is TypeParameter) {
      _typeParameter(full, partial);
      return partial;
    } else if (full is TypeParameterList && partial is TypeParameterList) {
      _typeParameterList(full, partial);
      return partial;
    } else if (full is VariableDeclaration && partial is VariableDeclaration) {
      _variableDeclaration(full, partial);
      return partial;
    } else if (full is VariableDeclarationList &&
        partial is VariableDeclarationList) {
      _variableDeclarationList(full, partial);
      return partial;
    } else {
      throw UnimplementedError(
        '${full.runtimeType} and ${partial.runtimeType}',
      );
    }
  }

  void _simpleFormalParameter(
    SimpleFormalParameter full,
    SimpleFormalParameter partial,
  ) {
    var element = _walker.getParameter();
    _match(partial.identifier, element);
    (partial as SimpleFormalParameterImpl).declaredElement = element;
    _metadata(partial.metadata, element);
    _node(full.type, partial.type);
  }

  void _topLevelVariableDeclaration(
    TopLevelVariableDeclaration full,
    TopLevelVariableDeclaration partial,
  ) {
    _node(full.variables, partial.variables);

    var first = partial.variables.variables[0];
    _metadata(partial.metadata, first.declaredElement);
  }

  void _typeName(TypeName full, TypeName partial) {
    var fullList = full.typeArguments?.arguments;
    var partialList = partial.typeArguments?.arguments;
    if (fullList != null && partialList != null) {
      for (var i = 0; i < fullList.length; ++i) {
        _node(fullList[i], partialList[i]);
      }
    }
  }

  void _typeParameter(TypeParameter full, TypeParameter partial) {
    var element = _walker.getTypeParameter();
    _match(partial.name, element);
    _node(full.bound, partial.bound);
    _metadata(partial.metadata, element);
  }

  void _typeParameterList(TypeParameterList full, TypeParameterList partial) {
    var fullList = full.typeParameters;
    var partialList = partial.typeParameters;
    for (var i = 0; i < fullList.length; ++i) {
      _node(fullList[i], partialList[i]);
    }
  }

  void _variableDeclaration(
    VariableDeclaration full,
    VariableDeclaration partial,
  ) {
    var element = _walker.getVariable();
    _match(partial.name, element);
    partial.initializer = full.initializer;
    {
      var elementBuilder = LocalElementBuilder(ElementHolder(), null);
      partial.initializer?.accept(elementBuilder);
    }
  }

  void _variableDeclarationList(
    VariableDeclarationList full,
    VariableDeclarationList partial,
  ) {
    _node(full.type, partial.type);

    var fullList = full.variables;
    var partialList = partial.variables;
    for (var i = 0; i < fullList.length; ++i) {
      _node(fullList[i], partialList[i]);
    }
  }

  void _walk(_ElementWalker walker, void f()) {
    var outer = _walker;
    _walker = walker;
    f();
    _walker = outer;
  }

  /// Associate [nodes] with the corresponding [ElementAnnotation]s.
  static void _metadata(List<Annotation> nodes, Element element) {
    var elements = element.metadata;
    if (nodes.length != elements.length) {
      throw StateError('Found ${nodes.length} annotation nodes and '
          '${elements.length} element annotations');
    }
    for (var i = 0; i < nodes.length; i++) {
      nodes[i].elementAnnotation = elements[i];
    }
  }
}

class _ElementWalker {
  final Element element;

  List<PropertyAccessorElement> _accessors;
  int _accessorIndex = 0;

  List<ClassElement> _classes;
  int _classIndex = 0;

  List<ConstructorElement> _constructors;
  int _constructorIndex = 0;

  List<ClassElement> _enums;
  int _enumIndex = 0;

  List<ExecutableElement> _functions;
  int _functionIndex = 0;

  List<ClassElement> _mixins;
  int _mixinIndex = 0;

  List<ParameterElement> _parameters;
  int _parameterIndex = 0;

  List<FunctionTypeAliasElement> _typedefs;
  int _typedefIndex = 0;

  List<TypeParameterElement> _typeParameters;
  int _typeParameterIndex = 0;

  List<VariableElement> _variables;
  int _variableIndex = 0;

  _ElementWalker.forClass(ClassElement element)
      : element = element,
        _accessors = element.accessors.where(_isNotSynthetic).toList(),
        _constructors = element.isMixinApplication
            ? null
            : element.constructors.where(_isNotSynthetic).toList(),
        _functions = element.methods,
        _typeParameters = element.typeParameters,
        _variables = element.fields.where(_isNotSynthetic).toList();

  _ElementWalker.forCompilationUnit(CompilationUnitElement element)
      : element = element,
        _accessors = element.accessors.where(_isNotSynthetic).toList(),
        _classes = element.types,
        _enums = element.enums,
        _functions = element.functions,
        _mixins = element.mixins,
        _typedefs = element.functionTypeAliases,
        _variables = element.topLevelVariables.where(_isNotSynthetic).toList();

  _ElementWalker.forExecutable(ExecutableElement element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  _ElementWalker.forGenericFunctionType(GenericFunctionTypeElement element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  _ElementWalker.forGenericTypeAlias(FunctionTypeAliasElement element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  _ElementWalker.forParameter(ParameterElement element)
      : element = element,
        _parameters = element.parameters,
        _typeParameters = element.typeParameters;

  PropertyAccessorElement getAccessor() {
    return _accessors[_accessorIndex++];
  }

  ClassElement getClass() {
    return _classes[_classIndex++];
  }

  ConstructorElement getConstructor() {
    return _constructors[_constructorIndex++];
  }

  ClassElement getEnum() {
    return _enums[_enumIndex++];
  }

  ExecutableElement getFunction() {
    return _functions[_functionIndex++];
  }

  ClassElement getMixin() {
    return _mixins[_mixinIndex++];
  }

  ParameterElement getParameter() {
    return _parameters[_parameterIndex++];
  }

  FunctionTypeAliasElement getTypedef() {
    return _typedefs[_typedefIndex++];
  }

  TypeParameterElement getTypeParameter() {
    return _typeParameters[_typeParameterIndex++];
  }

  VariableElement getVariable() {
    return _variables[_variableIndex++];
  }

  static bool _isNotSynthetic(Element e) => !e.isSynthetic;
}
