// Copyright (c) 2012, 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.

// @dart = 2.7

import 'dart:convert';

import 'package:compiler/compiler_api.dart' as api;
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/json_info_codec.dart';
import 'package:dart2js_info/binary_serialization.dart' as binary;
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';

const String TEST_BASIC = r"""
library main;

int a = 2;

class c {
  final int m;
  c(this.m) {
    () {} ();  // TODO (sigurdm): Empty closure, hack to avoid inlining.
    a = 1;
  }
  foo() {
    () {} ();
    k = 2;
    print(k);
    print(p);
  }
  var k = (() => 10)();
  static final p = 20;
}

void f() {
  () {} ();
  a = 3;
}

main() {
  print(a);
  f();
  print(new c(2).foo());
}
""";

const String TEST_CLOSURES = r"""
main() {
  print(bar);
  print(bar());
  print(new X().foo);
  print(new X().foo());
}

bar() => [() => [() => [() => [() => [() => [() => [() => [() => [() => [() =>
[() => []]]]]]]]]]]];

class X {
  foo() => [() => [() => [() => [() => [() => [() => [() => [() => [() =>
[() => []]]]]]]]]]];
}
""";

const String TEST_STATICS = r"""
class ContainsStatics {
  static int does_something() {
    try {
      print('hello');
      return 1;
    } finally {
      print('world');
      return 2;
    }
  }
}

void main() {
  print(ContainsStatics.does_something());
}
""";

const String TEST_INLINED_1 = r"""
class Doubler {
  int double(int x) {
    return x + 2;
  }
}
void main() {
  var f = new Doubler();
  print(f.double(4));
}
""";

const String TEST_INLINED_2 = r"""
  funcA() => funcB();
  funcB() => print("hello");
   main() => funcA();
""";

typedef InfoCheck = void Function(AllInfo);

infoTest(String program, bool useBinary, InfoCheck check) async {
  var options = ['--out=out.js', Flags.dumpInfo];
  // Note: we always pass '--dump-info' because the memory-compiler does not
  // have the logic in dart2js.dart to imply dump-info when --dump-info=binary
  // is provided.
  if (useBinary) options.add("${Flags.dumpInfo}=binary");
  var collector = new OutputCollector();
  var result = await runCompiler(
      memorySourceFiles: {'main.dart': program},
      options: options,
      outputProvider: collector);
  var compiler = result.compiler;
  Expect.isFalse(compiler.compilationFailed);
  AllInfo info;
  if (useBinary) {
    var sink = collector.binaryOutputMap[Uri.parse('out.js.info.data')];
    info = binary.decode(sink.list);
  } else {
    info = new AllInfoJsonCodec().decode(
        json.decode(collector.getOutput("out.js", api.OutputType.dumpInfo)));
  }
  check(info);
}

main() {
  asyncTest(() async {
    print('--test from kernel------------------------------------------------');
    await runTests(useBinary: false);
    await runTests(useBinary: true);
  });
}

runTests({bool useBinary: false}) async {
  await infoTest(TEST_BASIC, useBinary, (info) {
    Expect.isTrue(info.functions.isNotEmpty);
    Expect.isTrue(info.libraries.isNotEmpty);
    Expect.isTrue(info.libraries.any((lib) => lib.name == "main"));
    Expect.isTrue(info.classes.any((c) => c.name == 'c'));
    Expect.isTrue(info.functions.any((f) => f.name == 'f'));
  });

  await infoTest(TEST_CLOSURES, useBinary, (info) {
    Expect.isTrue(info.functions.any((fn) {
      return fn.name == 'bar' && fn.closures.length == 11;
    }));
    Expect.isTrue(info.functions.any((fn) {
      return fn.name == 'foo' && fn.closures.length == 10;
    }));
  });

  await infoTest(TEST_STATICS, useBinary, (info) {
    Expect.isTrue(info.functions.any((fn) => fn.name == 'does_something'));
    Expect.isTrue(info.classes.any((cls) {
      return cls.name == 'ContainsStatics' && cls.functions.length >= 1;
    }));
  });

  await infoTest(TEST_INLINED_1, useBinary, (info) {
    Expect.isTrue(info.functions.any((fn) {
      return fn.name == 'double' && fn.inlinedCount == 1;
    }));
    Expect.isTrue(info.classes.any((cls) {
      return cls.name == 'Doubler' && cls.functions.length >= 1;
    }));
  });

  await infoTest(TEST_INLINED_2, useBinary, (info) {
    var main_ = info.functions.firstWhere((v) => v.name == 'main');
    var fn1 = info.functions.firstWhere((v) => v.name == 'funcA');
    var fn2 = info.functions.firstWhere((v) => v.name == 'funcB');
    Expect.isTrue(main_ != null);
    Expect.isTrue(fn1 != null);
    Expect.isTrue(fn2 != null);
    Expect.isTrue(main_.uses.any((dep) => dep.target == fn1));
    Expect.isTrue(fn1.uses.any((dep) => dep.target == fn2));
  });
}
