// 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.dart';
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", 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));
  });
}
