// 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:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/enqueue.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
import 'package:compiler/src/universe/member_usage.dart';
import 'package:compiler/src/universe/resolution_world_builder.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'));
    print('------------------------------------------------------------------');
    print(' Test with enqueuer checks');
    print('------------------------------------------------------------------');
    await checkTests(dataDir, const ClosedWorldDataComputer(false),
        args: args, testedConfigs: allSpecConfigs);
    print('------------------------------------------------------------------');
    print(' Test without enqueuer checks');
    print('------------------------------------------------------------------');
    await checkTests(dataDir, const ClosedWorldDataComputer(true),
        args: args, testedConfigs: allSpecConfigs);
  });
}

class Tags {
  static const String init = 'init';
  static const String read = 'read';
  static const String write = 'write';
  static const String invoke = 'invoke';
}

class ClosedWorldDataComputer extends DataComputer<Features> {
  final bool skipEnqueuerCheck;

  const ClosedWorldDataComputer(this.skipEnqueuerCheck);

  @override
  void setup() {
    Enqueuer.skipEnqueuerCheckForTesting = skipEnqueuerCheck;
  }

  /// Compute a short textual representation of [access] on member.
  ///
  /// Dynamic access on instance members and static access on non-instance
  /// members is implicit, so we only annotate super access and static access
  /// not implied by dynamic or super access.
  String computeAccessText(MemberEntity member, EnumSet<Access> access,
      [String? prefix]) {
    StringBuffer sb = StringBuffer();
    String delimiter = '';
    if (prefix != null) {
      sb.write(prefix);
      delimiter = ':';
    }
    if (access.contains(Access.superAccess)) {
      sb.write(delimiter);
      sb.write('super');
    } else if (member.isInstanceMember &&
        access.contains(Access.staticAccess) &&
        !access.contains(Access.dynamicAccess)) {
      sb.write(delimiter);
      sb.write('static');
    }
    return sb.toString();
  }

  @override
  void computeMemberData(Compiler compiler, MemberEntity member,
      Map<Id, ActualData<Features>> actualMap,
      {bool verbose = false}) {
    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
    ResolutionWorldBuilder resolutionWorldBuilder =
        compiler.resolutionWorldBuilderForTesting!;
    ir.Member node = frontendStrategy.elementMap.getMemberNode(member);
    Features features = Features();
    MemberUsage? memberUsage =
        resolutionWorldBuilder.memberUsageForTesting[member];
    if (memberUsage != null) {
      if (member is FieldEntity && memberUsage.hasInit) {
        features.add(Tags.init);
      }
      if (memberUsage.hasRead) {
        features[Tags.read] = computeAccessText(member, memberUsage.reads);
      }
      if (memberUsage.hasWrite) {
        features[Tags.write] = computeAccessText(member, memberUsage.writes);
      }
      if (memberUsage.hasInvoke) {
        if (memberUsage is MethodUsage &&
            !memberUsage.parameterUsage.isFullyUsed) {
          features[Tags.invoke] = computeAccessText(member, memberUsage.invokes,
              memberUsage.invokedParameters!.shortText);
        } else {
          features[Tags.invoke] =
              computeAccessText(member, memberUsage.invokes);
        }
      }
    }
    Id id = computeMemberId(node);
    ir.TreeNode nodeWithOffset = computeTreeNodeWithOffset(node)!;
    actualMap[id] = ActualData<Features>(id, features,
        nodeWithOffset.location!.file, nodeWithOffset.fileOffset, member);
  }

  @override
  bool get testFrontend => true;

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