// 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 'dart:async';

import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart';

import '../executor.dart';
import '../api.dart';
import 'response_impls.dart';

class TypeBuilderBase implements IdentifierResolver {
  /// The final result, will be built up over `augment` calls.
  final List<DeclarationCode> _libraryAugmentations;

  /// The final result, will be built up over `augment` calls.
  final Map<String, List<DeclarationCode>> _classAugmentations;

  /// The names of any new types added in [_libraryAugmentations].
  final List<String> _newTypeNames = [];

  final IdentifierResolver identifierResolver;

  /// Creates and returns a [MacroExecutionResult] out of the [_augmentations]
  /// created by this builder.
  MacroExecutionResult get result => new MacroExecutionResultImpl(
        classAugmentations: _classAugmentations,
        libraryAugmentations: _libraryAugmentations,
        newTypeNames: _newTypeNames,
      );

  TypeBuilderBase(this.identifierResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : _classAugmentations = parentClassAugmentations ?? {},
        _libraryAugmentations = parentLibraryAugmentations ?? [];

  @override
  Future<Identifier> resolveIdentifier(Uri library, String identifier) =>
      // ignore: deprecated_member_use_from_same_package
      identifierResolver.resolveIdentifier(library, identifier);
}

class TypeBuilderImpl extends TypeBuilderBase implements TypeBuilder {
  TypeBuilderImpl(IdentifierResolver identifierResolver)
      : super(identifierResolver);

  @override
  void declareType(String name, DeclarationCode typeDeclaration) {
    _newTypeNames.add(name);
    _libraryAugmentations.add(typeDeclaration);
  }
}

/// Base class for all [DeclarationBuilder]s.
class DeclarationBuilderBase extends TypeBuilderBase
    implements ClassIntrospector, TypeResolver {
  final ClassIntrospector classIntrospector;
  final TypeResolver typeResolver;

  DeclarationBuilderBase(IdentifierResolver identifierResolver,
      this.classIntrospector, this.typeResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : super(identifierResolver,
            parentClassAugmentations: parentClassAugmentations,
            parentLibraryAugmentations: parentLibraryAugmentations);

  @override
  Future<List<ConstructorDeclaration>> constructorsOf(ClassDeclaration clazz) =>
      classIntrospector.constructorsOf(clazz);

  @override
  Future<List<FieldDeclaration>> fieldsOf(ClassDeclaration clazz) =>
      classIntrospector.fieldsOf(clazz);

  @override
  Future<List<ClassDeclaration>> interfacesOf(ClassDeclaration clazz) =>
      classIntrospector.interfacesOf(clazz);

  @override
  Future<List<MethodDeclaration>> methodsOf(ClassDeclaration clazz) =>
      classIntrospector.methodsOf(clazz);

  @override
  Future<List<ClassDeclaration>> mixinsOf(ClassDeclaration clazz) =>
      classIntrospector.mixinsOf(clazz);

  @override
  Future<ClassDeclaration?> superclassOf(ClassDeclaration clazz) =>
      classIntrospector.superclassOf(clazz);

  @override
  Future<StaticType> resolve(TypeAnnotationCode code) =>
      typeResolver.resolve(code);
}

class DeclarationBuilderImpl extends DeclarationBuilderBase
    implements DeclarationBuilder {
  DeclarationBuilderImpl(IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector, TypeResolver typeResolver)
      : super(identifierResolver, classIntrospector, typeResolver);

  @override
  void declareInLibrary(DeclarationCode declaration) {
    _libraryAugmentations.add(declaration);
  }
}

class ClassMemberDeclarationBuilderImpl extends DeclarationBuilderImpl
    implements ClassMemberDeclarationBuilder {
  final Identifier definingClass;

  ClassMemberDeclarationBuilderImpl(
      this.definingClass,
      IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector,
      TypeResolver typeResolver)
      : super(identifierResolver, classIntrospector, typeResolver);

  @override
  void declareInClass(DeclarationCode declaration) {
    _classAugmentations.update(
        definingClass.name, (value) => value..add(declaration),
        ifAbsent: () => [declaration]);
  }
}

/// Base class for all [DefinitionBuilder]s.
class DefinitionBuilderBase extends DeclarationBuilderBase
    implements TypeDeclarationResolver {
  final TypeDeclarationResolver typeDeclarationResolver;

  DefinitionBuilderBase(
      IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector,
      TypeResolver typeResolver,
      this.typeDeclarationResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : super(identifierResolver, classIntrospector, typeResolver,
            parentClassAugmentations: parentClassAugmentations,
            parentLibraryAugmentations: parentLibraryAugmentations);

  @override
  Future<TypeDeclaration> declarationOf(IdentifierImpl identifier) =>
      typeDeclarationResolver.declarationOf(identifier);
}

class ClassDefinitionBuilderImpl extends DefinitionBuilderBase
    implements ClassDefinitionBuilder {
  /// The declaration this is a builder for.
  final ClassDeclaration declaration;

  ClassDefinitionBuilderImpl(
      this.declaration,
      IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector,
      TypeResolver typeResolver,
      TypeDeclarationResolver typeDeclarationResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : super(identifierResolver, classIntrospector, typeResolver,
            typeDeclarationResolver,
            parentClassAugmentations: parentClassAugmentations,
            parentLibraryAugmentations: parentLibraryAugmentations);

  @override
  Future<ConstructorDefinitionBuilder> buildConstructor(
      Identifier identifier) async {
    ConstructorDeclaration constructor =
        (await classIntrospector.constructorsOf(declaration))
            .firstWhere((constructor) => constructor.identifier == identifier);
    return new ConstructorDefinitionBuilderImpl(constructor, identifierResolver,
        classIntrospector, typeResolver, typeDeclarationResolver,
        parentClassAugmentations: _classAugmentations,
        parentLibraryAugmentations: _libraryAugmentations);
  }

  @override
  Future<VariableDefinitionBuilder> buildField(Identifier identifier) async {
    FieldDeclaration field = (await classIntrospector.fieldsOf(declaration))
        .firstWhere((field) => field.identifier == identifier);
    return new VariableDefinitionBuilderImpl(field, identifierResolver,
        classIntrospector, typeResolver, typeDeclarationResolver,
        parentClassAugmentations: _classAugmentations,
        parentLibraryAugmentations: _libraryAugmentations);
  }

  @override
  Future<FunctionDefinitionBuilder> buildMethod(Identifier identifier) async {
    MethodDeclaration method = (await classIntrospector.methodsOf(declaration))
        .firstWhere((method) => method.identifier == identifier);
    return new FunctionDefinitionBuilderImpl(method, identifierResolver,
        classIntrospector, typeResolver, typeDeclarationResolver,
        parentClassAugmentations: _classAugmentations,
        parentLibraryAugmentations: _libraryAugmentations);
  }
}

/// Implementation of [FunctionDefinitionBuilder].
class FunctionDefinitionBuilderImpl extends DefinitionBuilderBase
    implements FunctionDefinitionBuilder {
  final FunctionDeclaration declaration;

  FunctionDefinitionBuilderImpl(
      this.declaration,
      IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector,
      TypeResolver typeResolver,
      TypeDeclarationResolver typeDeclarationResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : super(identifierResolver, classIntrospector, typeResolver,
            typeDeclarationResolver,
            parentClassAugmentations: parentClassAugmentations,
            parentLibraryAugmentations: parentLibraryAugmentations);

  @override
  void augment(FunctionBodyCode body) {
    DeclarationCode augmentation =
        _buildFunctionAugmentation(body, declaration);
    if (declaration is ClassMemberDeclaration) {
      _classAugmentations.update(
          (declaration as ClassMemberDeclaration).definingClass.name,
          (value) => value..add(augmentation),
          ifAbsent: () => [augmentation]);
    } else {
      _libraryAugmentations.add(augmentation);
    }
  }
}

class ConstructorDefinitionBuilderImpl extends DefinitionBuilderBase
    implements ConstructorDefinitionBuilder {
  final ConstructorDeclaration declaration;

  ConstructorDefinitionBuilderImpl(
      this.declaration,
      IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector,
      TypeResolver typeResolver,
      TypeDeclarationResolver typeDeclarationResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : super(identifierResolver, classIntrospector, typeResolver,
            typeDeclarationResolver,
            parentClassAugmentations: parentClassAugmentations,
            parentLibraryAugmentations: parentLibraryAugmentations);

  @override
  void augment({FunctionBodyCode? body, List<Code>? initializers}) {
    body ??= new FunctionBodyCode.fromString('''{
      augment super();
    }''');
    DeclarationCode augmentation = _buildFunctionAugmentation(body, declaration,
        initializers: initializers);
    _classAugmentations.update(
        declaration.definingClass.name, (value) => value..add(augmentation),
        ifAbsent: () => [augmentation]);
  }
}

class VariableDefinitionBuilderImpl extends DefinitionBuilderBase
    implements VariableDefinitionBuilder {
  final VariableDeclaration declaration;

  VariableDefinitionBuilderImpl(
      this.declaration,
      IdentifierResolver identifierResolver,
      ClassIntrospector classIntrospector,
      TypeResolver typeResolver,
      TypeDeclarationResolver typeDeclarationResolver,
      {Map<String, List<DeclarationCode>>? parentClassAugmentations,
      List<DeclarationCode>? parentLibraryAugmentations})
      : super(identifierResolver, classIntrospector, typeResolver,
            typeDeclarationResolver,
            parentClassAugmentations: parentClassAugmentations,
            parentLibraryAugmentations: parentLibraryAugmentations);

  @override
  void augment(
      {DeclarationCode? getter,
      DeclarationCode? setter,
      ExpressionCode? initializer}) {
    List<DeclarationCode> augmentations = _buildVariableAugmentations(
        declaration,
        getter: getter,
        setter: setter,
        initializer: initializer);
    if (declaration is ClassMemberDeclaration) {
      _classAugmentations.update(
          (declaration as ClassMemberDeclaration).definingClass.name,
          (value) => value..addAll(augmentations),
          ifAbsent: () => augmentations);
    } else {
      _libraryAugmentations.addAll(augmentations);
    }
  }
}

/// Builds all the possible augmentations for a variable.
List<DeclarationCode> _buildVariableAugmentations(
    VariableDeclaration declaration,
    {DeclarationCode? getter,
    DeclarationCode? setter,
    ExpressionCode? initializer}) {
  List<DeclarationCode> augmentations = [];
  if (getter != null) {
    augmentations.add(new DeclarationCode.fromParts([
      'augment ',
      if (declaration is FieldDeclaration && declaration.isStatic) 'static ',
      getter,
    ]));
  }
  if (setter != null) {
    augmentations.add(new DeclarationCode.fromParts([
      'augment ',
      if (declaration is FieldDeclaration && declaration.isStatic) 'static ',
      setter,
    ]));
  }
  if (initializer != null) {
    augmentations.add(new DeclarationCode.fromParts([
      'augment ',
      if (declaration is FieldDeclaration && declaration.isStatic) 'static ',
      if (declaration.isFinal) 'final ',
      declaration.type.code,
      ' ',
      declaration.identifier,
      ' = ',
      initializer,
      ';',
    ]));
  }

  return augmentations;
}

/// Builds the code to augment a function, method, or constructor with a new
/// body.
///
/// The [initializers] parameter can only be used if [declaration] is a
/// constructor.
DeclarationCode _buildFunctionAugmentation(
    FunctionBodyCode body, FunctionDeclaration declaration,
    {List<Code>? initializers}) {
  assert(initializers == null || declaration is ConstructorDeclaration);

  return new DeclarationCode.fromParts([
    'augment ',
    if (declaration is ConstructorDeclaration) ...[
      declaration.definingClass.name,
      if (declaration.identifier.name.isNotEmpty) '.',
    ] else ...[
      if (declaration is MethodDeclaration && declaration.isStatic) 'static ',
      declaration.returnType.code,
      ' ',
      if (declaration.isOperator) 'operator ',
    ],
    declaration.identifier.name,
    if (declaration.typeParameters.isNotEmpty) ...[
      '<',
      for (TypeParameterDeclaration typeParam
          in declaration.typeParameters) ...[
        typeParam.identifier.name,
        if (typeParam.bound != null) ...[' extends ', typeParam.bound!.code],
        if (typeParam != declaration.typeParameters.last) ', ',
      ],
      '>',
    ],
    '(',
    for (ParameterDeclaration positionalRequired
        in declaration.positionalParameters.takeWhile((p) => p.isRequired)) ...[
      positionalRequired.code,
      ', ',
    ],
    if (declaration.positionalParameters.any((p) => !p.isRequired)) ...[
      '[',
      for (ParameterDeclaration positionalOptional
          in declaration.positionalParameters.where((p) => !p.isRequired)) ...[
        positionalOptional.code,
        ', ',
      ],
      ']',
    ],
    if (declaration.namedParameters.isNotEmpty) ...[
      '{',
      for (ParameterDeclaration named in declaration.namedParameters) ...[
        named.code,
        ', ',
      ],
      '}',
    ],
    ') ',
    if (initializers != null && initializers.isNotEmpty) ...[
      ' : ',
      initializers.first,
      for (Code initializer in initializers.skip(1)) ...[
        ',\n',
        initializer,
      ],
    ],
    body,
  ]);
}
