// Copyright (c) 2018, 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 'package:async_helper/async_helper.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js_emitter/model.dart';
import 'package:compiler/src/js_model/js_world.dart' show JClosedWorld;
import 'package:expect/expect.dart';
import '../helpers/program_lookup.dart';
import 'package:compiler/src/util/memory_compiler.dart';

const String code = '''
// This needs one-arg instantiation.
@pragma('dart2js:noInline')
T f1a<T>(T t) => t;

// This needs no instantiation because it is not closurized.
@pragma('dart2js:noInline')
T f1b<T>(T t1, T t2) => t1;

class Class {
  // This needs two-arg instantiation.
  @pragma('dart2js:noInline')
  bool f2a<T, S>(T t, S s) => t == s;

  // This needs no instantiation because it is not closurized.
  @pragma('dart2js:noInline')
  bool f2b<T, S>(T t, S s1, S s2) => t == s1;
}

@pragma('dart2js:noInline')
int method1(int i, int Function(int) f) => f(i);

@pragma('dart2js:noInline')
bool method2(int a, int b, bool Function(int, int) f) => f(a, b);

@pragma('dart2js:noInline')
int method3(int a, int b, int c, int Function(int, int, int) f) => f(a, b, c);

main() {
  // This needs three-arg instantiation.
  T local1<T, S, U>(T t, S s, U u) => t;

  // This needs no instantiation because but a local function is always
  // closurized so we assume it does.
  T local2<T, S, U>(T t, S s, U u1, U u2) => t;

  print(method1(42, f1a));
  print(f1b(42, 87));

  Class c = Class();
  print(method2(0, 1, c.f2a));
  print(c.f2b(42, 87, 123));

  print(method3(0, 1, 2, local1));
  print(local2(42, 87, 123, 256));
}
''';

main() {
  asyncTest(() async {
    CompilationResult result = await runCompiler(
        memorySourceFiles: {'main.dart': code},
        options: [Flags.omitImplicitChecks]);
    Expect.isTrue(result.isSuccess);
    Compiler compiler = result.compiler!;
    JClosedWorld closedWorld = compiler.backendClosedWorldForTesting!;
    ProgramLookup programLookup = ProgramLookup(compiler.backendStrategy);

    void checkStubs(ClassEntity element, List<String> expectedStubs) {
      Class? cls = programLookup.getClass(element);
      List<String> actualStubs = <String>[];
      if (cls != null) {
        for (StubMethod stub in cls.callStubs) {
          actualStubs.add(stub.name!.key);
        }
      }
      Expect.setEquals(
          expectedStubs,
          actualStubs,
          "Unexpected stubs for $element:\n "
          "Expected: $expectedStubs\n Actual: $actualStubs");
    }

    checkStubs(closedWorld.commonElements.getInstantiationClass(1),
        [r'call$1', r'$signature']);
    checkStubs(closedWorld.commonElements.getInstantiationClass(2),
        [r'call$2', r'$signature']);
    checkStubs(closedWorld.commonElements.getInstantiationClass(3),
        [r'call$3', r'call$4', r'$signature']);
  });
}
