// 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/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';

import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/fasta/kernel/macro.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:kernel/ast.dart';

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 TestConfig(cfeMarker, 'cfe',
            explicitExperimentalFlags: {ExperimentalFlag.macros: true},
            packageConfigUri:
                Platform.script.resolve('data/package_config.json'))
      ]));
}

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

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

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

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

  @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 declaredMacros = 'declaredMacros';
  static const String appliedMacros = 'appliedMacros';
}

String importUriToString(Uri importUri) {
  if (importUri.scheme == 'package') {
    return importUri.toString();
  } else if (importUri.scheme == '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> {
  late final MacroDeclarationData macroDeclarationData;
  late final MacroApplicationData macroApplicationData;

  MacroDataExtractor(InternalCompilerResult compilerResult,
      Map<Id, ActualData<Features>> actualMap)
      : super(compilerResult, actualMap) {
    macroDeclarationData = compilerResult
        .kernelTargetForTesting!.loader.dataForTesting!.macroDeclarationData;
    macroApplicationData = compilerResult
        .kernelTargetForTesting!.loader.dataForTesting!.macroApplicationData;
  }

  LibraryMacroApplicationData? getLibraryMacroApplicationData(Library library) {
    return macroApplicationData.libraryData[library];
  }

  ClassMacroApplicationData? getClassMacroApplicationData(Class cls) {
    LibraryMacroApplicationData? applicationData =
        getLibraryMacroApplicationData(cls.enclosingLibrary);
    if (applicationData != null) {
      return applicationData.classData[cls];
    }
    return null;
  }

  MacroApplications? getClassMacroApplications(Class cls) {
    return getClassMacroApplicationData(cls)?.classApplications;
  }

  MacroApplications? getMemberMacroApplications(Member member) {
    Class? enclosingClass = member.enclosingClass;
    if (enclosingClass != null) {
      return getClassMacroApplicationData(enclosingClass)
          ?.memberApplications[member];
    } else {
      return getLibraryMacroApplicationData(member.enclosingLibrary)
          ?.memberApplications[member];
    }
  }

  void registerMacroApplications(
      Features features, MacroApplications? macroApplications) {
    if (macroApplications != null) {
      for (MacroApplication application in macroApplications.macros) {
        String className = application.cls.name;
        String constructorName = application.constructorName == ''
            ? 'new'
            : application.constructorName;
        features.addElement(
            Tags.appliedMacros, '${className}.${constructorName}');
      }
    }
  }

  @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));
        }
      }
    }
    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;
  }
}
