// Copyright (c) 2022, 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:_fe_analyzer_shared/src/macros/api.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
    as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart' as macro;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/macro_declarations.dart';

class LibraryMacroApplier {
  final MultiMacroExecutor macroExecutor;
  final DeclarationBuilder declarationBuilder;
  final LibraryBuilder libraryBuilder;

  final List<_MacroTarget> _targets = [];

  final macro.IdentifierResolver _identifierResolver = _IdentifierResolver();

  final macro.TypeResolver _typeResolver = _TypeResolver();

  late final macro.ClassIntrospector _classIntrospector =
      _ClassIntrospector(declarationBuilder);

  LibraryMacroApplier({
    required this.macroExecutor,
    required this.declarationBuilder,
    required this.libraryBuilder,
  });

  Linker get _linker => libraryBuilder.linker;

  /// Fill [_targets]s with macro applications.
  Future<void> buildApplications() async {
    final collector = _MacroTargetElementCollector();
    libraryBuilder.element.accept(collector);

    for (final targetElement in collector.targets) {
      final targetNode = _linker.elementNodes[targetElement];
      // TODO(scheglov) support other declarations
      if (targetNode is ClassDeclaration) {
        await _buildApplications(
          targetElement,
          targetNode.metadata,
          macro.DeclarationKind.clazz,
          () => declarationBuilder.fromNode.classDeclaration(targetNode),
        );
      }
    }
  }

  Future<String?> executeDeclarationsPhase() async {
    final results = <macro.MacroExecutionResult>[];
    for (final target in _targets) {
      for (final application in target.applications) {
        if (application.shouldExecute(macro.Phase.declarations)) {
          await _runWithCatchingExceptions(
            () async {
              final result = await application.executeDeclarationsPhase();
              if (result.isNotEmpty) {
                results.add(result);
              }
            },
            annotationIndex: application.annotationIndex,
            onError: (error) {
              target.element.macroApplicationErrors.add(error);
            },
          );
        }
      }
    }
    return _buildAugmentationLibrary(results);
  }

  Future<String?> executeTypesPhase() async {
    final results = <macro.MacroExecutionResult>[];
    for (final target in _targets) {
      for (final application in target.applications) {
        if (application.shouldExecute(macro.Phase.types)) {
          await _runWithCatchingExceptions(
            () async {
              final result = await application.executeTypesPhase();
              if (result.isNotEmpty) {
                results.add(result);
              }
            },
            annotationIndex: application.annotationIndex,
            onError: (error) {
              target.element.macroApplicationErrors.add(error);
            },
          );
        }
      }
    }
    return _buildAugmentationLibrary(results);
  }

  /// If there are any macro applications in [annotations], add a new
  /// element into [_targets].
  Future<void> _buildApplications(
    MacroTargetElement targetElement,
    List<Annotation> annotations,
    macro.DeclarationKind declarationKind,
    macro.DeclarationImpl Function() getDeclaration,
  ) async {
    final applications = <_MacroApplication>[];

    for (var i = 0; i < annotations.length; i++) {
      Future<macro.MacroInstanceIdentifier?> instantiateSingle({
        required ClassElementImpl macroClass,
        required String constructorName,
        required ArgumentList argumentsNode,
      }) async {
        final importedLibrary = macroClass.library;
        final macroExecutor = importedLibrary.bundleMacroExecutor;
        if (macroExecutor != null) {
          return await _runWithCatchingExceptions(
            () async {
              final arguments = _buildArguments(
                annotationIndex: i,
                node: argumentsNode,
              );
              return await macroExecutor.instantiate(
                libraryUri: macroClass.librarySource.uri,
                className: macroClass.name,
                constructorName: constructorName,
                arguments: arguments,
              );
            },
            annotationIndex: i,
            onError: (error) {
              targetElement.macroApplicationErrors.add(error);
            },
          );
        }
        return null;
      }

      final annotation = annotations[i];
      final macroInstance = await _importedMacroDeclaration(
        annotation,
        whenClass: ({
          required macroClass,
          required constructorName,
        }) async {
          final argumentsNode = annotation.arguments;
          if (argumentsNode != null) {
            return await instantiateSingle(
              macroClass: macroClass,
              constructorName: constructorName ?? '',
              argumentsNode: argumentsNode,
            );
          }
        },
        whenGetter: ({
          required macroClass,
          required instanceCreation,
        }) async {
          return await instantiateSingle(
            macroClass: macroClass,
            constructorName: instanceCreation.constructorName.name?.name ?? '',
            argumentsNode: instanceCreation.argumentList,
          );
        },
      );

      if (macroInstance != null) {
        applications.add(
          _MacroApplication(
            annotationIndex: i,
            instanceIdentifier: macroInstance,
          ),
        );
      }
    }

    if (applications.isNotEmpty) {
      _targets.add(
        _MacroTarget(
          applier: this,
          element: targetElement,
          declarationKind: declarationKind,
          declaration: getDeclaration(),
          applications: applications,
        ),
      );
    }
  }

  /// If there are any [results], builds the augmentation library with them.
  String? _buildAugmentationLibrary(
    List<macro.MacroExecutionResult> results,
  ) {
    if (results.isEmpty) {
      return null;
    }

    final code = macroExecutor.buildAugmentationLibrary(
      results,
      _resolveIdentifier,
      _inferOmittedType,
    );
    return code.trim();
  }

  /// If [annotation] references a macro, invokes the right callback.
  Future<R?> _importedMacroDeclaration<R>(
    Annotation annotation, {
    required Future<R?> Function({
      required ClassElementImpl macroClass,
      required String? constructorName,
    })
        whenClass,
    required Future<R?> Function({
      required ClassElementImpl macroClass,
      required InstanceCreationExpression instanceCreation,
    })
        whenGetter,
  }) async {
    final String? prefix;
    final String name;
    final String? constructorName;
    final nameNode = annotation.name;
    if (nameNode is SimpleIdentifier) {
      prefix = null;
      name = nameNode.name;
      constructorName = annotation.constructorName?.name;
    } else if (nameNode is PrefixedIdentifier) {
      final importPrefixCandidate = nameNode.prefix.name;
      final hasImportPrefix = libraryBuilder.element.imports
          .any((import) => import.prefix?.name == importPrefixCandidate);
      if (hasImportPrefix) {
        prefix = importPrefixCandidate;
        name = nameNode.identifier.name;
        constructorName = annotation.constructorName?.name;
      } else {
        prefix = null;
        name = nameNode.prefix.name;
        constructorName = nameNode.identifier.name;
      }
    } else {
      throw StateError('${nameNode.runtimeType} $nameNode');
    }

    for (final import in libraryBuilder.element.imports) {
      if (import.prefix?.name != prefix) {
        continue;
      }

      final importedLibrary = import.importedLibrary;
      if (importedLibrary == null) {
        continue;
      }

      // Skip if a library that is being linked.
      final importedUri = importedLibrary.source.uri;
      if (_linker.builders.containsKey(importedUri)) {
        continue;
      }

      final lookupResult = importedLibrary.scope.lookup(name);
      final element = lookupResult.getter;
      if (element is ClassElementImpl) {
        if (element.isMacro) {
          return await whenClass(
            macroClass: element,
            constructorName: constructorName,
          );
        }
      } else if (element is PropertyAccessorElementImpl &&
          element.isGetter &&
          element.isSynthetic) {
        final variable = element.variable;
        final variableType = variable.type;
        if (variable is ConstTopLevelVariableElementImpl &&
            variableType is InterfaceType) {
          final macroClass = variableType.element;
          final initializer = variable.constantInitializer;
          if (macroClass is ClassElementImpl &&
              macroClass.isMacro &&
              initializer is InstanceCreationExpression) {
            return await whenGetter(
              macroClass: macroClass,
              instanceCreation: initializer,
            );
          }
        }
      }
    }
    return null;
  }

  macro.TypeAnnotation _inferOmittedType(
    macro.OmittedTypeAnnotation omittedType,
  ) {
    throw UnimplementedError();
  }

  macro.ResolvedIdentifier _resolveIdentifier(macro.Identifier identifier) {
    throw UnimplementedError();
  }

  static macro.Arguments _buildArguments({
    required int annotationIndex,
    required ArgumentList node,
  }) {
    final positional = <Object?>[];
    final named = <String, Object?>{};
    for (var i = 0; i < node.arguments.length; ++i) {
      final argument = node.arguments[i];
      final evaluation = _ArgumentEvaluation(
        annotationIndex: annotationIndex,
        argumentIndex: i,
      );
      if (argument is NamedExpression) {
        final value = evaluation.evaluate(argument.expression);
        named[argument.name.label.name] = value;
      } else {
        final value = evaluation.evaluate(argument);
        positional.add(value);
      }
    }
    return macro.Arguments(positional, named);
  }

  /// Run the [body], report exceptions as [MacroApplicationError]s to [onError].
  static Future<T?> _runWithCatchingExceptions<T>(
    Future<T> Function() body, {
    required int annotationIndex,
    required void Function(MacroApplicationError) onError,
  }) async {
    try {
      return await body();
    } on MacroApplicationError catch (e) {
      onError(e);
    } on macro.RemoteException catch (e) {
      onError(
        UnknownMacroApplicationError(
          annotationIndex: annotationIndex,
          message: e.error,
          stackTrace: e.stackTrace ?? '<null>',
        ),
      );
    } catch (e, stackTrace) {
      onError(
        UnknownMacroApplicationError(
          annotationIndex: annotationIndex,
          message: e.toString(),
          stackTrace: stackTrace.toString(),
        ),
      );
    }
    return null;
  }
}

/// Helper class for evaluating arguments for a single constructor based
/// macro application.
class _ArgumentEvaluation {
  final int annotationIndex;
  final int argumentIndex;

  _ArgumentEvaluation({
    required this.annotationIndex,
    required this.argumentIndex,
  });

  Object? evaluate(Expression node) {
    if (node is AdjacentStrings) {
      return node.strings.map(evaluate).join('');
    } else if (node is BooleanLiteral) {
      return node.value;
    } else if (node is DoubleLiteral) {
      return node.value;
    } else if (node is IntegerLiteral) {
      return node.value;
    } else if (node is ListLiteral) {
      return node.elements.cast<Expression>().map(evaluate).toList();
    } else if (node is NullLiteral) {
      return null;
    } else if (node is PrefixExpression &&
        node.operator.type == TokenType.MINUS) {
      final operandValue = evaluate(node.operand);
      if (operandValue is double) {
        return -operandValue;
      } else if (operandValue is int) {
        return -operandValue;
      }
    } else if (node is SetOrMapLiteral) {
      return _setOrMapLiteral(node);
    } else if (node is SimpleStringLiteral) {
      return node.value;
    }
    _throwError(node, 'Not supported: ${node.runtimeType}');
  }

  Object _setOrMapLiteral(SetOrMapLiteral node) {
    if (node.elements.every((e) => e is Expression)) {
      final result = <Object?>{};
      for (final element in node.elements) {
        if (element is! Expression) {
          _throwError(element, 'Expression expected');
        }
        final value = evaluate(element);
        result.add(value);
      }
      return result;
    }

    final result = <Object?, Object?>{};
    for (final element in node.elements) {
      if (element is! MapLiteralEntry) {
        _throwError(element, 'MapLiteralEntry expected');
      }
      final key = evaluate(element.key);
      final value = evaluate(element.value);
      result[key] = value;
    }
    return result;
  }

  Never _throwError(AstNode node, String message) {
    throw ArgumentMacroApplicationError(
      annotationIndex: annotationIndex,
      argumentIndex: argumentIndex,
      message: message,
    );
  }
}

class _ClassIntrospector implements macro.ClassIntrospector {
  final DeclarationBuilder declarationBuilder;

  _ClassIntrospector(this.declarationBuilder);

  @override
  Future<List<macro.ConstructorDeclaration>> constructorsOf(
      covariant macro.ClassDeclaration clazz) {
    // TODO: implement constructorsOf
    throw UnimplementedError();
  }

  @override
  Future<List<macro.FieldDeclaration>> fieldsOf(macro.ClassDeclaration clazz) {
    // TODO: implement fieldsOf
    throw UnimplementedError();
  }

  @override
  Future<List<macro.ClassDeclaration>> interfacesOf(
      covariant macro.ClassDeclaration clazz) {
    // TODO: implement interfacesOf
    throw UnimplementedError();
  }

  @override
  Future<List<macro.MethodDeclaration>> methodsOf(
      covariant macro.ClassDeclaration clazz) {
    // TODO: implement methodsOf
    throw UnimplementedError();
  }

  @override
  Future<List<macro.ClassDeclaration>> mixinsOf(
      covariant macro.ClassDeclaration clazz) {
    // TODO: implement mixinsOf
    throw UnimplementedError();
  }

  @override
  Future<macro.ClassDeclaration?> superclassOf(
    covariant ClassDeclarationImpl clazz,
  ) async {
    final superType = clazz.element.supertype;
    if (superType == null) {
      return null;
    }

    return declarationBuilder.fromElement.classElement(
      superType.element,
    );
  }
}

class _IdentifierResolver extends macro.IdentifierResolver {
  @override
  Future<macro.Identifier> resolveIdentifier(Uri library, String name) {
    // TODO: implement resolveIdentifier
    throw UnimplementedError();
  }
}

class _MacroApplication {
  late final _MacroTarget target;
  final int annotationIndex;
  final macro.MacroInstanceIdentifier instanceIdentifier;

  _MacroApplication({
    required this.annotationIndex,
    required this.instanceIdentifier,
  });

  Future<macro.MacroExecutionResult> executeDeclarationsPhase() async {
    final applier = target.applier;
    final executor = applier.macroExecutor;
    return await executor.executeDeclarationsPhase(
      instanceIdentifier,
      target.declaration,
      applier._identifierResolver,
      applier._typeResolver,
      applier._classIntrospector,
    );
  }

  Future<macro.MacroExecutionResult> executeTypesPhase() async {
    final applier = target.applier;
    final executor = applier.macroExecutor;
    return await executor.executeTypesPhase(
      instanceIdentifier,
      target.declaration,
      applier._identifierResolver,
    );
  }

  bool shouldExecute(macro.Phase phase) {
    return instanceIdentifier.shouldExecute(target.declarationKind, phase);
  }
}

class _MacroTarget {
  final LibraryMacroApplier applier;
  final MacroTargetElement element;
  final macro.DeclarationKind declarationKind;
  final macro.DeclarationImpl declaration;
  final List<_MacroApplication> applications;

  _MacroTarget({
    required this.applier,
    required this.element,
    required this.declarationKind,
    required this.declaration,
    required this.applications,
  }) {
    for (final application in applications) {
      application.target = this;
    }
  }
}

class _MacroTargetElementCollector extends GeneralizingElementVisitor<void> {
  final List<MacroTargetElement> targets = [];

  @override
  void visitElement(covariant ElementImpl element) {
    if (element is MacroTargetElement) {
      targets.add(element as MacroTargetElement);
    }
    if (element is MacroTargetElementContainer) {
      element.visitChildren(this);
    }
  }
}

class _TypeResolver implements macro.TypeResolver {
  @override
  Future<macro.StaticType> resolve(macro.TypeAnnotationCode type) {
    // TODO: implement resolve
    throw UnimplementedError();
  }
}

extension on macro.MacroExecutionResult {
  bool get isNotEmpty =>
      libraryAugmentations.isNotEmpty || classAugmentations.isNotEmpty;
}
