import 'dart:async';

import 'package:socket_io_client/socket_io_client.dart';

import '../../errors/custom_exception.dart';

extension Converter on Socket {
  Future<dynamic> emitAsync(String event, dynamic body) async {
    Future<dynamic> convert(
      String eventName,
      dynamic body,
      void Function(
        String eventName,
        dynamic body, {
        void Function(dynamic)? ack,
      }) func,
    ) {
      Completer completer = Completer();

      func(eventName, body, ack: (result) {
        if (completer.isCompleted) return;
        completer.complete(result);
      });

      Future.delayed(const Duration(seconds: 2)).then((value) {
        if (completer.isCompleted) return;
        completer.completeError(
            GenericException(type: ExceptionType.connectionError));
      });

      return completer.future;
    }

    return await convert(event, body, emitWithAck);
  }

  Future<dynamic> connectAsync() async {
    Completer completer = Completer();

    connect();

    onConnect((data) {
      if (completer.isCompleted) return;
      completer.complete(data);
    });

    onConnectError((data) {
      if (completer.isCompleted) return;
      completer
          .completeError(GenericException(type: ExceptionType.connectionError));
    });

    onConnectTimeout((data) {
      if (completer.isCompleted) return;
      completer
          .completeError(GenericException(type: ExceptionType.connectionError));
    });

    return completer.future;
  }

  Future<dynamic> disconnectAsync() async {
    Completer completer = Completer();

    disconnect();

    onDisconnect(
        (data) => completer.isCompleted ? null : completer.complete(data));

    return completer.future;
  }
}
