// 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,
      ),
    );
  }

  @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 visitImportDirective(ImportDirective node) {
    setData(
      node,
      UnlinkedInformativeDataBuilder.importDirective(
        directiveKeywordOffset: node.keyword.offset,
      ),
    );
  }

  @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 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);
  }
}
