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