// Copyright (c) 2020, 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.
//
// Sample showing how to do async callbacks by telling the Dart isolate to
// yields its execution thread to C so it can perform the callbacks on the
// main Dart thread.
//
// TODO(dartbug.com/37022): Update this when we get real async callbacks.

import 'dart:ffi';
import 'dart:isolate';

import 'package:expect/expect.dart';

import '../dylib_utils.dart';

int globalResult = 0;
int numCallbacks1 = 0;
int numCallbacks2 = 0;

main() async {
  print("Dart = Dart mutator thread executing Dart.");
  print("C Da = Dart mutator thread executing C.");
  print("C T1 = Some C thread executing C.");
  print("C T2 = Some C thread executing C.");
  print("C    = C T1 or C T2.");
  print("Dart: Setup.");
  Expect.isTrue(NativeApi.majorVersion == 2);
  Expect.isTrue(NativeApi.minorVersion >= 0);
  final initializeApi = dl.lookupFunction<IntPtr Function(Pointer<Void>),
      int Function(Pointer<Void>)>("InitDartApiDL");
  Expect.isTrue(initializeApi(NativeApi.initializeApiDLData) == 0);

  final interactiveCppRequests = ReceivePort()..listen(requestExecuteCallback);
  final int nativePort = interactiveCppRequests.sendPort.nativePort;
  registerCallback1(nativePort, callback1FP);
  registerCallback2(nativePort, callback2FP);
  print("Dart: Tell C to start worker threads.");
  startWorkSimulator();

  // We need to yield control in order to be able to receive messages.
  while (numCallbacks2 < 3) {
    print("Dart: Yielding (able to receive messages on port).");
    await asyncSleep(500);
  }
  print("Dart: Received expected number of callbacks.");

  Expect.equals(2, numCallbacks1);
  Expect.equals(3, numCallbacks2);
  Expect.equals(14, globalResult);

  print("Dart: Tell C to stop worker threads.");
  stopWorkSimulator();
  interactiveCppRequests.close();
  print("Dart: Done.");
}

int callback1(int a) {
  print("Dart:     callback1($a).");
  numCallbacks1++;
  return a + 3;
}

void callback2(int a) {
  print("Dart:     callback2($a).");
  globalResult += a;
  numCallbacks2++;
}

void requestExecuteCallback(dynamic message) {
  final int work_address = message;
  final work = Pointer<Work>.fromAddress(work_address);
  print("Dart:   Calling into C to execute callback ($work).");
  executeCallback(work);
  print("Dart:   Done with callback.");
}

final callback1FP = Pointer.fromFunction<IntPtr Function(IntPtr)>(callback1, 0);

final callback2FP = Pointer.fromFunction<Void Function(IntPtr)>(callback2);

final dl = dlopenPlatformSpecific("ffi_test_functions");

final registerCallback1 = dl.lookupFunction<
        Void Function(Int64 sendPort,
            Pointer<NativeFunction<IntPtr Function(IntPtr)>> functionPointer),
        void Function(int sendPort,
            Pointer<NativeFunction<IntPtr Function(IntPtr)>> functionPointer)>(
    'RegisterMyCallbackBlocking');

final registerCallback2 = dl.lookupFunction<
        Void Function(Int64 sendPort,
            Pointer<NativeFunction<Void Function(IntPtr)>> functionPointer),
        void Function(int sendPort,
            Pointer<NativeFunction<Void Function(IntPtr)>> functionPointer)>(
    'RegisterMyCallbackNonBlocking');

final startWorkSimulator =
    dl.lookupFunction<Void Function(), void Function()>('StartWorkSimulator');

final stopWorkSimulator =
    dl.lookupFunction<Void Function(), void Function()>('StopWorkSimulator');

final executeCallback = dl.lookupFunction<Void Function(Pointer<Work>),
    void Function(Pointer<Work>)>('ExecuteCallback');

class Work extends Opaque {}

Future asyncSleep(int ms) {
  return new Future.delayed(Duration(milliseconds: ms));
}
