// Copyright (c) 2019, 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';
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:expect/async_helper.dart';
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js_backend/annotations.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:compiler/src/util/enumset.dart';
import 'package:kernel/ast.dart' as ir;
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';

main(List<String> args) {
  asyncTest(() async {
    Directory dataDir = Directory.fromUri(Platform.script.resolve('data'));
    await checkTests(
      dataDir,
      const AnnotationDataComputer(),
      args: args,
      testedConfigs: allSpecConfigs,
    );
  });
}

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

  /// Compute type inference data for [member] from kernel based inference.
  ///
  /// Fills [actualMap] with the data.
  @override
  void computeMemberData(
    Compiler compiler,
    MemberEntity member,
    Map<Id, ActualData<String>> actualMap, {
    bool verbose = false,
  }) {
    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting!;
    JsToElementMap elementMap = closedWorld.elementMap;
    MemberDefinition definition = elementMap.getMemberDefinition(member);
    AnnotationIrComputer(
      compiler.reporter,
      actualMap,
      elementMap,
      member,
      closedWorld.closureDataLookup,
      closedWorld.annotationsData as AnnotationsDataImpl,
    ).run(definition.node);
  }

  @override
  bool get supportsErrors => true;

  @override
  String computeErrorData(
    Compiler compiler,
    Id id,
    List<CollectedMessage> errors,
  ) {
    return '[${errors.map((error) => error.message!.message).join(',')}]';
  }

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

/// AST visitor for computing inference data for a member.
class AnnotationIrComputer extends IrDataExtractor<String> {
  final JsToElementMap _elementMap;
  final ClosureData _closureDataLookup;
  final AnnotationsDataImpl _annotationData;

  AnnotationIrComputer(
    DiagnosticReporter reporter,
    Map<Id, ActualData<String>> actualMap,
    this._elementMap,
    MemberEntity member,
    this._closureDataLookup,
    this._annotationData,
  ) : super(reporter, actualMap);

  String? getMemberValue(MemberEntity member) {
    EnumSet<PragmaAnnotation>? pragmas =
        _annotationData.pragmaAnnotations[member];
    if (pragmas != null) {
      Features features = Features();
      for (PragmaAnnotation pragma in pragmas.iterable(
        PragmaAnnotation.values,
      )) {
        features.add(pragma.name);
      }
      return features.getText();
    }
    return null;
  }

  @override
  String? computeMemberValue(Id id, ir.Member node) {
    return getMemberValue(_elementMap.getMember(node));
  }

  @override
  String? computeNodeValue(Id id, ir.TreeNode node) {
    if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(
        node as ir.LocalFunction,
      );
      return getMemberValue(info.callMethod as FunctionEntity);
    }
    if (node is ir.LoadLibrary) {
      return _annotationData.getLoadLibraryPriority(node);
    }
    return null;
  }
}
