// 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, File, 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_shared/serialization.dart';
import 'package:_fe_analyzer_shared/src/macros/isolated_executor/isolated_executor.dart'
    as isolatedExecutor;
import 'package:_fe_analyzer_shared/src/testing/id.dart'
    show ActualData, ClassId, Id, LibraryId;
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/field_builder.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/kernel/macro.dart';
import 'package:front_end/src/fasta/kernel/utils.dart';
import 'package:front_end/src/fasta/source/source_class_builder.dart';
import 'package:front_end/src/fasta/source/source_library_builder.dart';
import 'package:front_end/src/testing/compiler_common.dart';
import 'package:front_end/src/testing/id_extractor.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:kernel/ast.dart' hide Arguments;
import 'package:kernel/kernel.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/text/ast_to_text.dart';
import 'package:vm/target/vm.dart';

import '../utils/kernel_chain.dart';

Future<void> main(List<String> args) async {
  bool generateExpectations = args.contains('-g');
  enableMacros = true;

  Directory tempDirectory =
      await Directory.systemTemp.createTemp('macro_application');
  try {
    Directory dataDir =
        new Directory.fromUri(Platform.script.resolve('data/tests'));
    await runTests<String>(dataDir,
        args: args,
        createUriForFileName: createUriForFileName,
        onFailure: onFailure,
        runTest: runTestFor(const MacroDataComputer(), [
          new MacroTestConfig(dataDir, tempDirectory,
              generateExpectations: generateExpectations)
        ]),
        preserveWhitespaceInAnnotations: true);
  } finally {
    await tempDirectory.delete(recursive: true);
  }
}

class MacroTestConfig extends TestConfig {
  final Directory dataDir;
  final Directory tempDirectory;
  final bool generateExpectations;
  int precompiledCount = 0;
  final Map<MacroClass, Uri> precompiledMacroUris = {};

  MacroTestConfig(this.dataDir, this.tempDirectory,
      {required this.generateExpectations})
      : super(cfeMarker, 'cfe',
            explicitExperimentalFlags: {ExperimentalFlag.macros: true},
            packageConfigUri:
                Platform.script.resolve('data/package_config.json'));

  @override
  void customizeCompilerOptions(CompilerOptions options, TestData testData) {
    options.macroExecutorProvider = () async {
      return await isolatedExecutor.start(SerializationMode.byteDataServer);
    };
    options.precompiledMacroUris = precompiledMacroUris;
    options.macroTarget = new VmTarget(new TargetFlags());
    options.macroSerializer = (Component component) async {
      Uri uri = tempDirectory.absolute.uri
          .resolve('macros${precompiledCount++}.dill');
      await writeComponentToFile(component, uri);
      return uri;
    };
  }

  @override
  Future<void> onCompilationResult(
      TestData testData, TestResultData testResultData) async {
    Component component = testResultData.compilerResult.component!;
    StringBuffer buffer = new StringBuffer();
    Printer printer = new Printer(buffer)
      ..writeProblemsAsJson("Problems in component", component.problemsAsJson);
    component.libraries.forEach((Library library) {
      if (isTestUri(library.importUri)) {
        printer.writeLibraryFile(library);
        printer.endLine();
      }
    });
    printer.writeConstantTable(component);
    String actual = buffer.toString();
    String expectationFileName = '${testData.name}.expect';
    Uri expectedUri = dataDir.uri.resolve(expectationFileName);
    File file = new File.fromUri(expectedUri);
    if (file.existsSync()) {
      String expected = file.readAsStringSync();
      if (expected != actual) {
        if (generateExpectations) {
          file.writeAsStringSync(actual);
        } else {
          String diff = await runDiff(expectedUri, actual);
          throw "${testData.name} don't match ${expectedUri}\n$diff";
        }
      }
    } else if (generateExpectations) {
      file.writeAsStringSync(actual);
    } else {
      throw 'Please use -g option to create file ${expectedUri} with this '
          'content:\n$actual';
    }
  }
}

bool _isMember(MemberBuilder memberBuilder, Member member) {
  if (memberBuilder is FieldBuilder) {
    // Only show annotations for the field or getter.
    return memberBuilder.readTarget == member;
  } else if (member is Procedure && member.isSetter) {
    return memberBuilder.writeTarget == member;
  } else if (member is Procedure && member.isGetter) {
    return memberBuilder.readTarget == member;
  } else {
    return memberBuilder.invokeTarget == member;
  }
}

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

  @override
  DataInterpreter<String> get dataValidator => const StringDataInterpreter();

  @override
  void computeLibraryData(TestResultData testResultData, Library library,
      Map<Id, ActualData<String>> actualMap,
      {bool? verbose}) {
    CfeDataRegistry<String> registry =
        new CfeDataRegistry(testResultData.compilerResult, actualMap);
    MacroApplicationDataForTesting macroApplicationData = testResultData
        .compilerResult
        .kernelTargetForTesting!
        .loader
        .dataForTesting!
        .macroApplicationData;
    StringBuffer sb = new StringBuffer();
    for (SourceLibraryBuilder sourceLibraryBuilder
        in macroApplicationData.libraryTypesResult.keys) {
      if (sourceLibraryBuilder.library == library) {
        String source =
            macroApplicationData.libraryTypesResult[sourceLibraryBuilder]!;
        sb.write('\n${source}');
      }
    }
    if (sb.isNotEmpty) {
      Id id = new LibraryId(library.fileUri);
      registry.registerValue(
          library.fileUri, library.fileOffset, id, sb.toString(), library);
    }
  }

  @override
  void computeClassData(TestResultData testResultData, Class cls,
      Map<Id, ActualData<String>> actualMap,
      {bool? verbose}) {
    CfeDataRegistry<String> registry =
        new CfeDataRegistry(testResultData.compilerResult, actualMap);
    MacroApplicationDataForTesting macroApplicationData = testResultData
        .compilerResult
        .kernelTargetForTesting!
        .loader
        .dataForTesting!
        .macroApplicationData;
    StringBuffer sb = new StringBuffer();
    for (MapEntry<SourceClassBuilder, List<MacroExecutionResult>> entry
        in macroApplicationData.classTypesResults.entries) {
      if (entry.key.cls == cls) {
        for (MacroExecutionResult result in entry.value) {
          sb.write('\n${codeToString(result.augmentations.first)}');
        }
      }
    }
    for (MapEntry<SourceClassBuilder, List<MacroExecutionResult>> entry
        in macroApplicationData.classDeclarationsResults.entries) {
      if (entry.key.cls == cls) {
        for (MacroExecutionResult result in entry.value) {
          sb.write('\n${codeToString(result.augmentations.first)}');
        }
      }
    }
    for (MapEntry<SourceClassBuilder, List<MacroExecutionResult>> entry
        in macroApplicationData.classDefinitionsResults.entries) {
      if (entry.key.cls == cls) {
        for (MacroExecutionResult result in entry.value) {
          sb.write('\n${codeToString(result.augmentations.first)}');
        }
      }
    }
    if (sb.isNotEmpty) {
      Id id = new ClassId(cls.name);
      registry.registerValue(
          cls.fileUri, cls.fileOffset, id, sb.toString(), cls);
    }
  }

  @override
  void computeMemberData(TestResultData testResultData, Member member,
      Map<Id, ActualData<String>> actualMap,
      {bool? verbose}) {
    CfeDataRegistry<String> registry =
        new CfeDataRegistry(testResultData.compilerResult, actualMap);
    MacroApplicationDataForTesting macroApplicationData = testResultData
        .compilerResult
        .kernelTargetForTesting!
        .loader
        .dataForTesting!
        .macroApplicationData;
    StringBuffer sb = new StringBuffer();
    for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
        in macroApplicationData.memberTypesResults.entries) {
      if (_isMember(entry.key, member)) {
        for (MacroExecutionResult result in entry.value) {
          sb.write('\n${codeToString(result.augmentations.first)}');
        }
      }
    }
    for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
        in macroApplicationData.memberDeclarationsResults.entries) {
      if (_isMember(entry.key, member)) {
        for (MacroExecutionResult result in entry.value) {
          sb.write('\n${codeToString(result.augmentations.first)}');
        }
      }
    }
    for (MapEntry<MemberBuilder, List<MacroExecutionResult>> entry
        in macroApplicationData.memberDefinitionsResults.entries) {
      if (_isMember(entry.key, member)) {
        for (MacroExecutionResult result in entry.value) {
          sb.write('\n${codeToString(result.augmentations.first)}');
        }
      }
    }
    if (sb.isNotEmpty) {
      Id id = computeMemberId(member);
      registry.registerValue(
          member.fileUri, member.fileOffset, id, sb.toString(), member);
    }
  }
}

void _codeToString(StringBuffer sb, Code code) {
  for (Object part in code.parts) {
    if (part is Code) {
      _codeToString(sb, part);
    } else if (part is Identifier) {
      sb.write(part.name);
    } else {
      sb.write(part);
    }
  }
}

String codeToString(Code code) {
  StringBuffer sb = new StringBuffer();
  _codeToString(sb, code);
  return sb.toString();
}
