// 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/ast/visitor.dart';
import 'package:analyzer/src/summary/format.dart';

/// Create informative data for nodes that need it, and set IDs of this
/// data to the nodes.
List<UnlinkedInformativeDataBuilder> createInformativeData(
    CompilationUnit unit) {
  var visitor = _SetInformativeId();
  unit.accept(visitor);
  return visitor.dataList;
}

/// If [createInformativeData] set the informative data identifier for the
/// [node], return it, otherwise return zero.
int getInformativeId(AstNode node) {
  int id = node.getProperty(_SetInformativeId.ID);
  return id ?? 0;
}

class _SetInformativeId extends SimpleAstVisitor<void> {
  static final String ID = 'informativeId';

  final List<UnlinkedInformativeDataBuilder> dataList = [];

  void setData(AstNode node, UnlinkedInformativeDataBuilder data) {
    var id = 1 + dataList.length;
    node.setProperty(ID, id);
    dataList.add(data);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.classDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.typeParameters?.accept(this);
    node.members.accept(this);
  }

  @override
  void visitClassTypeAlias(ClassTypeAlias node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.classTypeAlias(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.typeParameters?.accept(this);
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.compilationUnit(
        codeOffset: node.offset,
        codeLength: node.length,
        compilationUnit_lineStarts: node.lineInfo.lineStarts,
      ),
    );

    node.directives.accept(this);
    node.declarations.accept(this);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.constructorDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name?.offset ?? 0,
        constructorDeclaration_periodOffset: node.period?.offset ?? 0,
        constructorDeclaration_returnTypeOffset: node.returnType.offset,
      ),
    );

    node.parameters?.accept(this);
  }

  @override
  void visitDefaultFormalParameter(DefaultFormalParameter node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.defaultFormalParameter(
        codeOffset: node.offset,
        codeLength: node.length,
      ),
    );

    node.parameter.accept(this);
  }

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.enumConstantDeclaration(
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );
  }

  @override
  void visitEnumDeclaration(EnumDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.enumDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.constants.accept(this);
  }

  @override
  void visitExportDirective(ExportDirective node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.exportDirective(
        directiveKeywordOffset: node.keyword.offset,
      ),
    );
    node.combinators.accept(this);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.extensionDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name?.offset ?? 0,
      ),
    );

    node.typeParameters?.accept(this);
    node.members.accept(this);
  }

  @override
  void visitFieldDeclaration(FieldDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.fieldDeclaration(
        documentationComment_tokens: _nodeCommentTokens(node),
      ),
    );

    node.fields.accept(this);
  }

  @override
  void visitFieldFormalParameter(FieldFormalParameter node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.fieldFormalParameter(
        codeOffset: node.offset,
        codeLength: node.length,
        nameOffset: node.identifier.offset,
      ),
    );
  }

  @override
  void visitFormalParameterList(FormalParameterList node) {
    node.parameters.accept(this);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.functionDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.functionExpression.accept(this);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    node.typeParameters?.accept(this);
    node.parameters?.accept(this);
  }

  @override
  void visitFunctionTypeAlias(FunctionTypeAlias node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.functionTypeAlias(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.typeParameters?.accept(this);
    node.parameters.accept(this);
  }

  @override
  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.functionTypedFormalParameter(
        codeOffset: node.offset,
        codeLength: node.length,
        nameOffset: node.identifier.offset,
      ),
    );
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    node.typeParameters?.accept(this);
    node.parameters.accept(this);
  }

  @override
  void visitGenericTypeAlias(GenericTypeAlias node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.genericTypeAlias(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.typeParameters?.accept(this);
    node.functionType?.accept(this);
  }

  @override
  void visitHideCombinator(HideCombinator node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.hideCombinator(
        combinatorEnd: node.end,
        combinatorKeywordOffset: node.offset,
      ),
    );
  }

  @override
  void visitImportDirective(ImportDirective node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.importDirective(
        directiveKeywordOffset: node.keyword.offset,
        importDirective_prefixOffset: node.prefix?.offset ?? 0,
      ),
    );
    node.combinators.accept(this);
  }

  @override
  void visitLibraryDirective(LibraryDirective node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.libraryDirective(
        documentationComment_tokens: _nodeCommentTokens(node),
      ),
    );
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.methodDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.typeParameters?.accept(this);
    node.parameters?.accept(this);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.mixinDeclaration(
        codeOffset: node.offset,
        codeLength: node.length,
        documentationComment_tokens: _nodeCommentTokens(node),
        nameOffset: node.name.offset,
      ),
    );

    node.typeParameters?.accept(this);
    node.members.accept(this);
  }

  @override
  void visitPartDirective(PartDirective node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.partDirective(
        directiveKeywordOffset: node.keyword.offset,
      ),
    );
  }

  @override
  void visitPartOfDirective(PartOfDirective node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.partDirective(
        directiveKeywordOffset: node.keyword.offset,
      ),
    );
  }

  @override
  void visitShowCombinator(ShowCombinator node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.showCombinator(
        combinatorEnd: node.end,
        combinatorKeywordOffset: node.offset,
      ),
    );
  }

  @override
  void visitSimpleFormalParameter(SimpleFormalParameter node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.simpleFormalParameter(
        codeOffset: node.offset,
        codeLength: node.length,
        nameOffset: node.identifier?.offset ?? 0,
      ),
    );
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.topLevelVariableDeclaration(
        documentationComment_tokens: _nodeCommentTokens(node),
      ),
    );

    node.variables.accept(this);
  }

  @override
  void visitTypeParameter(TypeParameter node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.typeParameter(
        codeOffset: node.offset,
        codeLength: node.length,
        nameOffset: node.name.offset,
      ),
    );
  }

  @override
  void visitTypeParameterList(TypeParameterList node) {
    node.typeParameters.accept(this);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    var variableList = node.parent as VariableDeclarationList;
    var isFirst = identical(variableList.variables[0], node);
    var codeOffset = (isFirst ? variableList.parent : node).offset;
    var codeLength = node.end - codeOffset;

    setData(
      node,
      UnlinkedInformativeDataBuilder.variableDeclaration(
        codeOffset: codeOffset,
        codeLength: codeLength,
        nameOffset: node.name.offset,
      ),
    );
  }

  @override
  void visitVariableDeclarationList(VariableDeclarationList node) {
    node.variables.accept(this);
  }

  static List<String> _commentTokens(Comment comment) {
    if (comment == null) return null;
    return comment.tokens.map((token) => token.lexeme).toList();
  }

  static List<String> _nodeCommentTokens(AnnotatedNode node) {
    return _commentTokens(node.documentationComment);
  }
}
