// Copyright (c) 2021, 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/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/macro/api/code.dart';
import 'package:analyzer/src/macro/api/macro.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/library_builder.dart';

class ClassDeclarationBuilderImpl extends DeclarationBuilderImpl
    implements ClassDeclarationBuilder {
  final LinkingUnit linkingUnit;

  /// The index of [node] among other [ast.ClassDeclarationImpl]s.
  final int nodeIndex;

  final ast.ClassDeclarationImpl node;

  ClassDeclarationBuilderImpl(
    this.linkingUnit,
    this.nodeIndex,
    this.node,
  );

  @override
  void addToClass(Declaration declaration) {
    var declarationCode = declaration.code.trim();

    // TODO(scheglov) feature set
    // TODO(scheglov) throw if errors?
    var parseResult = parseString(
      content: 'class ${node.name.name} { $declarationCode }',
    );
    var parsedDeclarations = parseResult.unit.declarations;
    var parsedClass = parsedDeclarations.single as ast.ClassDeclaration;
    var parsedMember = parsedClass.members.single;
    _rebaseOffsets(parsedMember);

    node.members.add(parsedMember);

    var macroGeneratedContent = linkingUnit.macroGeneratedContent;
    var collected = _Declaration(
      data: MacroGenerationData(
        id: macroGeneratedContent.nextId++,
        code: declarationCode,
        informative: writeDeclarationInformative(parsedMember),
        classDeclarationIndex: nodeIndex,
      ),
      node: parsedMember,
    );
    macroGeneratedContent._declarations.add(collected);
  }

  /// We parsed [node] in the context of some synthetic code string, its
  /// current offsets only have meaning relative to the begin offset of the
  /// [node]. So, we update offsets accordingly.
  static void _rebaseOffsets(ast.AstNode node) {
    var baseOffset = node.offset;
    for (Token? t = node.beginToken;
        t != null && t != node.endToken;
        t = t.next) {
      t.offset -= baseOffset;
    }
  }
}

class DeclarationBuilderImpl implements DeclarationBuilder {
  @override
  void addToLibrary(Declaration declaration) {
    // TODO: implement addToLibrary
  }

  @override
  Code typeAnnotationCode(ast.TypeAnnotation node) {
    return Fragment(node.toSource());
  }
}

class MacroGeneratedContent {
  final LinkingUnit linkingUnit;
  final List<_Declaration> _declarations = [];
  int nextId = 0;

  MacroGeneratedContent(this.linkingUnit);

  /// Finish building of elements: combine the source code of the unit with
  /// macro-generated pieces of code; update offsets of macro-generated
  /// elements to use offsets inside this combined code.
  void finish() {
    // Don't set empty values, keep it null.
    if (_declarations.isEmpty) {
      return;
    }

    // Sort declarations by:
    // 1. The top-level declaration location.
    // 2. The ordering in the top-level declaration.
    // We need (2) because `sort` is not stable.
    _declarations.sort((a, b) {
      const indexForUnit = 1 << 24;
      var aIndex = a.data.classDeclarationIndex ?? indexForUnit;
      var bIndex = b.data.classDeclarationIndex ?? indexForUnit;
      if (aIndex != bIndex) {
        return aIndex - bIndex;
      }
      return a.data.id - b.data.id;
    });

    const classMemberCodePrefix = '\n  ';
    const classMemberCodeSuffix = '\n';
    // TODO(scheglov) make it required?
    var generatedContent = linkingUnit.input.sourceContent!;
    var shift = 0;
    var classDeclarations = linkingUnit.input.unit.declarations
        .whereType<ast.ClassDeclaration>()
        .toList();
    for (var declaration in _declarations) {
      var classIndex = declaration.data.classDeclarationIndex;
      if (classIndex != null) {
        var targetClass = classDeclarations[classIndex];
        var code = classMemberCodePrefix +
            declaration.data.code +
            classMemberCodeSuffix;
        var insertOffset = shift + targetClass.rightBracket.offset;
        declaration.data.offset = insertOffset + classMemberCodePrefix.length;
        generatedContent = generatedContent.substring(0, insertOffset) +
            code +
            generatedContent.substring(insertOffset);
        shift += code.length;
      } else {
        throw UnimplementedError();
      }

      var node = declaration.node;
      if (node is ast.Declaration) {
        var element = node.declaredElement as ElementImpl;
        element.accept(
          _ShiftOffsetsElementVisitor(declaration.data.offset),
        );
        if (element is HasMacroGenerationData) {
          (element as HasMacroGenerationData).macro = declaration.data;
        }
      }
    }

    linkingUnit.element.macroGeneratedContent = generatedContent;
    linkingUnit.element.macroGenerationDataList =
        _declarations.map((e) => e.data).toList();
  }
}

/// [MacroGenerationData] plus its linking [node] (to get the element).
class _Declaration {
  final MacroGenerationData data;
  final ast.AstNode node;

  _Declaration({
    required this.data,
    required this.node,
  });
}

/// TODO(scheglov) Enhance to support more nodes.
/// For now only nodes that are currently used in tests are supported.
/// Which is probably enough for experiments, but should be improved if this
/// is something we are going to do for real.
class _ShiftOffsetsAstVisitor extends RecursiveAstVisitor<void> {
  final int shift;

  _ShiftOffsetsAstVisitor(this.shift);

  @override
  void visitAnnotation(ast.Annotation node) {
    _token(node.atSign);
    super.visitAnnotation(node);
  }

  @override
  void visitSimpleIdentifier(ast.SimpleIdentifier node) {
    _token(node.token);
  }

  void _token(Token token) {
    token.offset += shift;
  }
}

/// Macro-generated elements are created from pieces of code that are rebased
/// to start at zero-th offset. When we later know that actual offset in the
/// combined (source + generated) code of the unit, we shift the offsets.
class _ShiftOffsetsElementVisitor extends GeneralizingElementVisitor<void> {
  final int shift;

  _ShiftOffsetsElementVisitor(this.shift);

  @override
  void visitElement(covariant ElementImpl element) {
    element.nameOffset += shift;
    _metadata(element.metadata);
    super.visitElement(element);
  }

  void _metadata(List<ElementAnnotation> metadata) {
    for (var annotation in metadata) {
      annotation as ElementAnnotationImpl;
      annotation.annotationAst.accept(
        _ShiftOffsetsAstVisitor(shift),
      );
    }
  }
}
