// Copyright (c) 2025, 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:async';
import 'dart:convert';
import 'dart:ffi';
import 'dart:isolate';
import 'dart:io';

import 'package:ffi/ffi.dart';

import 'dylib_utils.dart';

Function (Pointer<Utf8>) createGetSender(final SendPort sendPort) {
  return (Pointer<Utf8> responsePointer) {
    final typedList = responsePointer.cast<Uint8>().asTypedList(
          responsePointer.length,
        );
    sendPort.send(utf8.decode(typedList));
  };
}

// Runs a simple HTTP GET request using a native HTTP library that runs
// the request on a background thread.
Future<String> httpGet(String uri) async {
  // Create the NativeCallable.listener.
  final completer = Completer<String>();
  final ReceivePort rp = ReceivePort()
    ..listen(
      (string) {
        completer.complete(string);
      },
      onError: (e, st) {
        print('httpGet receiver get error $e $st');
      },
    );
  final callback = NativeCallable<HttpCallback>.isolateGroupBound(
      createGetSender(rp.sendPort));

  // Invoke the native HTTP API. Our example HTTP library runs our GET
  // request on a background thread, and calls the callback on that same
  // thread when it receives the response.
  final uriPointer = uri.toNativeUtf8();
  nativeHttpGet(uriPointer, callback.nativeFunction);
  calloc.free(uriPointer);

  // Wait for the response.
  final response = await completer.future;

  rp.close();
  callback.close();

  return response;
}

@pragma('vm:shared')
late int counter;

Function (Pointer<Utf8>) createServeSender(final SendPort sendPort) {
  return (Pointer<Utf8> requestPointer) {
    counter++;
    final typedList = requestPointer.cast<Uint8>().asTypedList(
          requestPointer.length,
        );
    sendPort.send(utf8.decode(typedList));
  };
}

// Start a HTTP server on a background thread.
ReceivePort httpServe(void Function(String) onRequest) {
  counter = 0;
  final rp = ReceivePort();
  final callback = NativeCallable<HttpCallback>.isolateGroupBound(
      createServeSender(rp.sendPort));
  rp.listen(
    (s) {
      print('httpServe counter: $counter');
      onRequest(s);
    },
    onError: (e, st) {
      print('httpServe receiver get error $e $st');
    },
    onDone: () {
      nativeHttpStopServing();
      callback.close();
    },
  );

  // Invoke the native function to start the HTTP server. Our example
  // HTTP library will start a server on a background thread, and pass
  // any requests it receives to out callback.
  nativeHttpStartServing(callback.nativeFunction);

  return rp;
}

// Load the native functions from a DynamicLibrary.
late final DynamicLibrary dylib = dlopenPlatformSpecific(
  'fake_httpIG',
  paths: [
    Platform.script.resolve('../lib/'),
    Uri.file(Platform.resolvedExecutable),
  ],
);
typedef HttpCallback = Void Function(Pointer<Utf8>);

typedef HttpGetFunction = void Function(
    Pointer<Utf8>, Pointer<NativeFunction<HttpCallback>>);
typedef HttpGetNativeFunction = Void Function(
    Pointer<Utf8>, Pointer<NativeFunction<HttpCallback>>);
final nativeHttpGet =
    dylib.lookupFunction<HttpGetNativeFunction, HttpGetFunction>('http_get');

typedef HttpStartServingFunction = bool Function(
    Pointer<NativeFunction<HttpCallback>>);
typedef HttpStartServingNativeFunction = Bool Function(
    Pointer<NativeFunction<HttpCallback>>);
final nativeHttpStartServing = dylib
    .lookupFunction<HttpStartServingNativeFunction, HttpStartServingFunction>(
  'http_start_serving',
);

typedef HttpStopServingFunction = void Function();
typedef HttpStopServingNativeFunction = Void Function();
final nativeHttpStopServing = dylib
    .lookupFunction<HttpStopServingNativeFunction, HttpStopServingFunction>(
  'http_stop_serving',
);

Future<void> main() async {
  print('Sending GET request...');
  final response = await httpGet('http://example.com');
  print('Received a response: $response');

  print('Starting HTTP server...');
  final rpServer = httpServe((String request) {
    print('Received a request: $request');
  });

  await Future.delayed(Duration(seconds: 10));
  print('All done');

  rpServer.close();
}
