// 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:io' show Directory, Platform;

import 'package:_fe_analyzer_shared/src/macros/api.dart';
import 'package:_fe_analyzer_shared/src/macros/executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/serialization.dart';
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/fasta/builder/class_builder.dart';
import 'package:front_end/src/fasta/builder/library_builder.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/kernel/macro/macro.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart' hide Arguments;

Future<void> main(List<String> args) async {
  enableMacros = true;

  Directory dataDir =
      new Directory.fromUri(Platform.script.resolve('data/tests'));
  await runTests<Features>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      runTest: runTestFor(const MacroDataComputer(), [new MacroTestConfig()]));
}

class MacroTestConfig extends TestConfig {
  MacroTestConfig()
      : super(cfeMarker, 'cfe',
            explicitExperimentalFlags: {ExperimentalFlag.macros: true},
            packageConfigUri:
                Platform.script.resolve('data/package_config.json'));

  @override
  TestMacroExecutor customizeCompilerOptions(
      CompilerOptions options, TestData testData) {
    TestMacroExecutor testExecutor =
        options.macroExecutor = new TestMacroExecutor();
    testExecutor.registerExecutorFactory(() => testExecutor,
        {Uri.parse('package:precompiled_macro/precompiled_macro.dart')});
    return testExecutor;
  }
}

class MacroDataComputer extends DataComputer<Features> {
  const MacroDataComputer();

  @override
  void computeMemberData(TestResultData testResultData, Member member,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    member.accept(new MacroDataExtractor(testResultData, actualMap));
  }

  @override
  void computeClassData(TestResultData testResultData, Class cls,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new MacroDataExtractor(testResultData, actualMap).computeForClass(cls);
  }

  @override
  void computeLibraryData(TestResultData testResultData, Library library,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new MacroDataExtractor(testResultData, actualMap)
        .computeForLibrary(library);
  }

  @override
  bool get supportsErrors => true;

  @override
  Features? computeErrorData(
      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
    Features features = new Features();
    features[Tags.error] = errorsToText(errors, useCodes: true);
    return features;
  }

  @override
  DataInterpreter<Features> get dataValidator =>
      const FeaturesDataInterpreter();
}

class Tags {
  static const String macrosAreAvailable = 'macrosAreAvailable';
  static const String macrosAreApplied = 'macrosAreApplied';
  static const String compilationSequence = 'compilationSequence';
  static const String neededPrecompilations = 'neededPrecompilations';
  static const String declaredMacros = 'declaredMacros';
  static const String appliedMacros = 'appliedMacros';
  static const String macroInstanceIds = 'macroInstanceIds';
  static const String error = 'error';
}

String constructorNameToString(String constructorName) {
  return constructorName == '' ? 'new' : constructorName;
}

String importUriToString(Uri importUri) {
  if (importUri.isScheme('package')) {
    return importUri.toString();
  } else if (importUri.isScheme('dart')) {
    return importUri.toString();
  } else {
    return importUri.pathSegments.last;
  }
}

String libraryToString(Library library) => importUriToString(library.importUri);

String strongComponentToString(Iterable<Uri> uris) {
  List<String> list = uris.map(importUriToString).toList();
  list.sort();
  return list.join('|');
}

class MacroDataExtractor extends CfeDataExtractor<Features> {
  final TestResultData testResultData;

  MacroDataExtractor(
      this.testResultData, Map<Id, ActualData<Features>> actualMap)
      : super(testResultData.compilerResult, actualMap);

  TestMacroExecutor get macroExecutor => testResultData.customData;

  MacroDeclarationData get macroDeclarationData => testResultData.compilerResult
      .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;

  MacroApplicationDataForTesting get macroApplicationData => testResultData
      .compilerResult
      .kernelTargetForTesting!
      .loader
      .dataForTesting!
      .macroApplicationData;

  LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
    for (MapEntry<LibraryBuilder, LibraryMacroApplicationData> entry
        in macroApplicationData.libraryData.entries) {
      if (entry.key.library == library) {
        return entry.value;
      }
    }
    return null;
  }

  ClassMacroApplicationData? getClassMacroApplicationData(Class cls) {
    LibraryMacroApplicationData? applicationData =
        getLibraryMacroApplicationData(cls.enclosingLibrary);
    if (applicationData != null) {
      for (MapEntry<ClassBuilder, ClassMacroApplicationData> entry
          in applicationData.classData.entries) {
        if (entry.key.cls == cls) {
          return entry.value;
        }
      }
    }
    return null;
  }

  List<MacroApplication>? getClassMacroApplications(Class cls) {
    return getClassMacroApplicationData(cls)
        ?.classApplications
        ?.macroApplications;
  }

  List<MacroApplication>? getMemberMacroApplications(Member member) {
    Class? enclosingClass = member.enclosingClass;
    Map<MemberBuilder, ApplicationData>? memberApplications;
    if (enclosingClass != null) {
      memberApplications =
          getClassMacroApplicationData(enclosingClass)?.memberApplications;
    } else {
      memberApplications =
          getLibraryMacroApplicationData(member.enclosingLibrary)
              ?.memberApplications;
    }
    if (memberApplications != null) {
      for (MapEntry<MemberBuilder, ApplicationData> entry
          in memberApplications.entries) {
        if (entry.key.member == member) {
          return entry.value.macroApplications;
        }
      }
    }
    return null;
  }

  void registerMacroApplications(
      Features features, List<MacroApplication>? macroApplications) {
    if (macroApplications != null) {
      for (MacroApplication application in macroApplications) {
        features.addElement(Tags.appliedMacros, application.toString());
      }
    }
  }

  @override
  Features computeClassValue(Id id, Class node) {
    Features features = new Features();
    if (getClassMacroApplicationData(node) != null) {
      features.add(Tags.macrosAreApplied);
    }
    registerMacroApplications(features, getClassMacroApplications(node));
    return features;
  }

  @override
  Features computeLibraryValue(Id id, Library node) {
    Features features = new Features();
    if (macroDeclarationData.macrosAreAvailable) {
      features.add(Tags.macrosAreAvailable);
    }
    if (node == compilerResult.component!.mainMethod!.enclosingLibrary) {
      if (macroDeclarationData.compilationSequence != null) {
        features.markAsUnsorted(Tags.compilationSequence);
        for (List<Uri> component in macroDeclarationData.compilationSequence!) {
          features.addElement(
              Tags.compilationSequence, strongComponentToString(component));
        }
      }
      for (Map<Uri, Map<String, List<String>>> precompilation
          in macroDeclarationData.neededPrecompilations) {
        Map<String, Map<String, List<String>>> converted =
            new Map.fromIterables(precompilation.keys.map(importUriToString),
                precompilation.values);
        List<String> uris = converted.keys.toList()..sort();
        StringBuffer sb = new StringBuffer();
        for (String uri in uris) {
          sb.write(uri);
          sb.write('=');
          Map<String, List<String>> macros = converted[uri]!;
          List<String> classes = macros.keys.toList()..sort();
          String delimiter = '';
          for (String cls in classes) {
            List<String> constructorNames =
                macros[cls]!.map(constructorNameToString).toList()..sort();
            sb.write(delimiter);
            sb.write(cls);
            sb.write('(');
            sb.write(constructorNames.join('/'));
            sb.write(')');
            delimiter = '|';
          }
        }
        features.addElement(Tags.neededPrecompilations, sb.toString());
      }
      for (_MacroInstanceIdentifier id in macroExecutor.macroInstances) {
        features.addElement(Tags.macroInstanceIds, id.toText());
      }
    }
    List<String>? macroClasses =
        macroDeclarationData.macroDeclarations[node.importUri];
    if (macroClasses != null) {
      for (String clsName in macroClasses) {
        features.addElement(Tags.declaredMacros, clsName);
      }
    }
    if (getLibraryMacroApplicationData(node) != null) {
      features.add(Tags.macrosAreApplied);
    }

    return features;
  }

  @override
  Features computeMemberValue(Id id, Member node) {
    Features features = new Features();
    registerMacroApplications(features, getMemberMacroApplications(node));
    return features;
  }
}

class TestMacroExecutor extends MultiMacroExecutor {
  List<_MacroInstanceIdentifier> macroInstances = [];

  @override
  String buildAugmentationLibrary(
      Iterable<MacroExecutionResult> macroResults,
      ResolvedIdentifier Function(Identifier) resolveIdentifier,
      TypeAnnotation? Function(OmittedTypeAnnotation) inferOmittedType,
      {Map<OmittedTypeAnnotation, String>? omittedTypes}) {
    return '';
  }

  @override
  Future<void> close() async {
    // TODO: implement close
  }

  @override
  Future<MacroExecutionResult> executeDeclarationsPhase(
      MacroInstanceIdentifier macro,
      Declaration declaration,
      IdentifierResolver identifierResolver,
      TypeResolver typeResolver,
      ClassIntrospector classIntrospector) async {
    return new _MacroExecutionResult();
  }

  @override
  Future<MacroExecutionResult> executeDefinitionsPhase(
      MacroInstanceIdentifier macro,
      Declaration declaration,
      IdentifierResolver identifierResolver,
      TypeResolver typeResolver,
      ClassIntrospector classIntrospector,
      TypeDeclarationResolver typeDeclarationResolver,
      TypeInferrer typeInferrer) async {
    return new _MacroExecutionResult();
  }

  @override
  Future<MacroExecutionResult> executeTypesPhase(MacroInstanceIdentifier macro,
      Declaration declaration, IdentifierResolver identifierResolver) async {
    return new _MacroExecutionResult();
  }

  @override
  Future<MacroInstanceIdentifier> instantiateMacro(
      Uri library, String name, String constructor, Arguments arguments) async {
    _MacroInstanceIdentifier id =
        new _MacroInstanceIdentifier(library, name, constructor, arguments);
    macroInstances.add(id);
    return id;
  }
}

class _MacroInstanceIdentifier implements MacroInstanceIdentifier {
  final Uri library;
  final String name;
  final String constructor;
  final Arguments arguments;

  _MacroInstanceIdentifier(
      this.library, this.name, this.constructor, this.arguments);

  String toText() => '${importUriToString(library)}/${name}/'
      '${constructor}${arguments.toText()}';

  @override
  void serialize(Serializer serializer) => throw UnimplementedError();

  @override
  bool shouldExecute(DeclarationKind declarationKind, Phase phase) => false;

  @override
  bool supportsDeclarationKind(DeclarationKind declarationKind) => false;
}

class _MacroExecutionResult implements MacroExecutionResult {
  @override
  Map<String, Iterable<DeclarationCode>> classAugmentations = const {};

  @override
  Iterable<DeclarationCode> libraryAugmentations = const [];

  @override
  Iterable<String> newTypeNames = const [];

  @override
  void serialize(Serializer serializer) {
    throw UnimplementedError();
  }
}

extension on Arguments {
  String toText() {
    StringBuffer sb = new StringBuffer();
    sb.write('(');
    String comma = '';
    for (Object? positional in positional) {
      sb.write(comma);
      sb.write(positional);
      comma = ',';
    }
    for (MapEntry<String, Object?> named in named.entries) {
      sb.write(comma);
      sb.write(named.key);
      sb.write(':');
      sb.write(named.value);
      comma = ',';
    }
    sb.write(')');
    return sb.toString();
  }
}
