// Copyright (c) 2019, 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 'dart:developer';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
import 'common/test_helper.dart';

int globalVar = 100;

class MyClass {
  static int staticVar = 1000;

  static void method(int value) {
    debugger();
  }
}

class _MyClass {
  void foo() {
    debugger();
  }
}

void testFunction() {
  int i = 0;
  while (true) {
    if (++i % 100000000 == 0) {
      MyClass.method(10000);
      (new _MyClass()).foo();
    }
  }
}

var tests = <IsolateTest>[
  hasStoppedAtBreakpoint,

// Evaluate against library, class, and instance.
  (VmService service, IsolateRef isolateRef) async {
    final isolate = await service.getIsolate(isolateRef.id);
    final stack = await service.getStack(isolateRef.id);

    // Make sure we are in the right place.
    expect(stack.frames.length, greaterThanOrEqualTo(2));
    expect(stack.frames[0].function.name, 'method');
    expect((stack.frames[0].function.owner as ClassRef).name, 'MyClass');

    final LibraryRef lib = isolate.rootLib;
    final ClassRef cls = stack.frames[0].function.owner;
    final InstanceRef instance = stack.frames[0].vars[0].value;

    dynamic result =
        await service.evaluate(isolate.id, lib.id, 'globalVar + 5');
    print(result);
    expect(result.valueAsString, '105');

    await expectError(() =>
        service.evaluate(isolate.id, lib.id, 'globalVar + staticVar + 5'));

    result =
        await service.evaluate(isolate.id, cls.id, 'globalVar + staticVar + 5');
    print(result);
    expect(result.valueAsString, '1105');

    await expectError(() => service.evaluate(isolate.id, cls.id, 'this + 5'));

    result = await service.evaluate(isolate.id, instance.id, 'this + 5');
    print(result);
    expect(result.valueAsString, '10005');

    await expectError(
        () => service.evaluate(isolate.id, instance.id, 'this + frog'));
  },
  resumeIsolate,
  hasStoppedAtBreakpoint,
  (VmService service, IsolateRef isolate) async {
    final stack = await service.getStack(isolate.id);

    // Make sure we are in the right place.
    expect(stack.frames.length, greaterThanOrEqualTo(2));
    expect(stack.frames[0].function.name, 'foo');
    expect((stack.frames[0].function.owner as ClassRef).name, '_MyClass');

    final ClassRef cls = stack.frames[0].function.owner;

    final InstanceRef result =
        await service.evaluate(isolate.id, cls.id, "1+1");
    print(result);
    expect(result.valueAsString, "2");
  }
];

expectError(func) async {
  bool gotException = false;
  dynamic result;
  try {
    result = await func();
    fail('Failed to throw');
  } on RPCError catch (e) {
    expect(e.code, 113); // Compile time error.
    gotException = true;
  }
  if (result?.type != 'Error') {
    expect(gotException, true); // dart2 semantics
  }
}

main([args = const <String>[]]) =>
    runIsolateTests(args, tests, testeeConcurrent: testFunction);
