// 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/world.dart';
import 'package:expect/expect.dart';
import '../helpers/program_lookup.dart';
import '../helpers/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 = new 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 = new 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']);
  });
}
