// 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/compiler.dart';
import 'package:compiler/src/universe/call_structure.dart';
import 'package:compiler/src/universe/world_builder.dart';
import 'package:expect/expect.dart';

import '../helpers/memory_compiler.dart';

const String code = r'''
import 'package:meta/dart2js.dart';

class Class1 {
  @noInline
  method1<T>() {}

  @noInline
  method2<T>() => T;

  @noInline
  method3<T>() => T;

  @noInline
  method4<T>() => T;

  @noInline
  method5<T>() => T;

  @noInline
  method6<T>() {}
}

class Class2 {}

class Class3 implements Class1 {
  @noInline
  method1<T>() {}

  @noInline
  method2<T>() {}

  @noInline
  method3<T>() {}

  @noInline
  method4<T>() {}

  @noInline
  method5<T>() {}

  @noInline
  method6<T>() {}
}

main(args) {
  dynamic c1 = args != null ? new Class1() : new Class2();
  c1.method1(); // No type arguments are inferred here.

  dynamic c2 = args != null ? new Class1() : new Class2();
  c2.method2<int>();

  var c3 = args != null ? new Class1() : new Class3();
  c3.method3(); // Type arguments are inferred here.

  var c4 = args != null ? new Class1() : new Class3();
  c4.method4<int>();

  dynamic c5 = args != null ? new Class1() : new Class2();
  c5.method5(); // No type arguments are inferred here.

  var c6 = args != null ? new Class1() : new Class3();
  c6.method5();  // Type arguments are inferred here.

  dynamic c7 = args != null ? new Class1() : new Class2();
  c7.method6<int>(); // Type arguments are not needed.

  var c8 = args != null ? new Class1() : new Class3();
  c8.method6(); // Type arguments are inferred here but not needed.
}
''';

main() {
  asyncTest(() async {
    CompilationResult result =
        await runCompiler(memorySourceFiles: {'main.dart': code});
    Expect.isTrue(result.isSuccess);
    Compiler compiler = result.compiler;
    CodegenWorldBuilder worldBuilder = compiler.codegenWorldBuilder;

    CallStructure noTypeArguments = new CallStructure(0, [], 0);
    CallStructure oneTypeArgument = new CallStructure(0, [], 1);

    Iterable<CallStructure> getCallStructures(String name) {
      return worldBuilder
              .invocationsByName(name)
              ?.keys
              ?.map((s) => s.callStructure) ??
          [];
    }

    void checkInvocationsFor(
        String methodName, List<CallStructure> expectedCallStructures) {
      Iterable<CallStructure> actualCallStructures =
          getCallStructures(methodName);
      Expect.setEquals(
          expectedCallStructures,
          actualCallStructures,
          "Unexpected call structures for '$methodName'. "
          "Expected ${expectedCallStructures}, "
          "actual ${actualCallStructures}.");
    }

    checkInvocationsFor('method1', [noTypeArguments]);
    checkInvocationsFor('method2', [oneTypeArgument]);
    checkInvocationsFor('method3', [oneTypeArgument]);
    checkInvocationsFor('method4', [oneTypeArgument]);
    checkInvocationsFor('method5', [noTypeArguments, oneTypeArgument]);
    checkInvocationsFor('method6', [noTypeArguments]);
  });
}
