// Copyright (c) 2020, 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: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_model/element_map.dart';
import 'package:compiler/src/js_model/js_strategy.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:kernel/ast.dart' as ir;
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';

const List<String> skip = [];

main(List<String> args) {
  runTests(args);
}

runTests(List<String> args, [int? shardIndex]) {
  runTestsCommon(
    args,
    shardIndex: shardIndex,
    shards: 2,
    directory: 'data',
    skip: skip,
    options: const [],
  );
}

runTestsCommon(
  List<String> args, {
  int? shardIndex,
  required int shards,
  required String directory,
  required List<String> options,
  required List<String> skip,
}) {
  asyncTest(() async {
    Directory dataDir = Directory.fromUri(Platform.script.resolve(directory));
    await checkTests(
      dataDir,
      const CodegenDataComputer(),
      forUserLibrariesOnly: true,
      args: args,
      options: options,
      testedConfigs: allInternalConfigs + [canaryConfig],
      skip: skip,
      shardIndex: shardIndex ?? 0,
      shards: shardIndex == null ? 1 : shards,
    );
  });
}

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

  /// Compute generated code for [member].
  ///
  /// 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);
    CodegenIrComputer(
      compiler.reporter,
      actualMap,
      elementMap,
      member,
      compiler.backendStrategy,
      closedWorld.closureDataLookup,
    ).run(definition.node);
  }

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

/// AST visitor for computing codegen data for a member.
class CodegenIrComputer extends IrDataExtractor<String> {
  final JsBackendStrategy _backendStrategy;
  final JsToElementMap _elementMap;
  final ClosureData _closureDataLookup;

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

  String? getMemberValue(MemberEntity member) {
    if (member is FunctionEntity) {
      return _backendStrategy.getGeneratedCodeForTesting(member);
    }
    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!);
    }
    return null;
  }
}

/// Default data interpreter for string data representing compiled JavaScript
/// code.
///
/// The data annotation reader strips out newlines and indentation so the
/// comparison needs to compensate.
///
/// The special data annotation `ignore` always passes, so we don't have to
/// track uninteresting code like a 'main' program.
class CodeDataInterpreter implements DataInterpreter<String> {
  const CodeDataInterpreter();

  String _clean(String code) => code.replaceAll(_re, '');
  static final RegExp _re = RegExp(r'[\n\r]\s*');

  @override
  String? isAsExpected(String? actualData, String? expectedData) {
    actualData ??= '';
    expectedData ??= '';
    if (expectedData == 'ignore') return null;
    if (_clean(actualData) != _clean(expectedData)) {
      return 'Expected $expectedData, found $actualData';
    }
    return null;
  }

  @override
  bool isEmpty(String actualData) {
    return _clean(actualData) == '';
  }

  @override
  String getText(String actualData, [String? indentation]) {
    return actualData;
  }
}
