import 'package:protobuf/protobuf.dart';

import 'communicator.dart';
import 'packets/message_common.pb.dart';
import 'response_checker.dart';

mixin HeartbeatMixin on Communicator {
  late int _heartbeatIntervalTime;
  late int _heartbeatWaitTime;
  ResponseChecker<Communicator>? _heartbeatChecker;
  bool _waitingHeartbeatResponse = false;

  Future<void> close();

  void initHeartbeat(int intervalSec, int waitSec) {
    _heartbeatIntervalTime = intervalSec;
    _heartbeatWaitTime = waitSec;
  }

  void sendHeartBeat() {
    if (isAlive) {
      _heartbeatChecker?.responded();
      _heartbeatChecker =
          ResponseChecker.second(this, _heartbeatIntervalTime, (client) {
        if (isAlive) {
          _waitingHeartbeatResponse = true;
          send(HeartBeat());
          _heartbeatChecker =
              ResponseChecker.second(this, _heartbeatWaitTime, (client) {
            if (isAlive) {
              close();
            }
          });
        }
      });
    }
  }

  void onHeartBeat(HeartBeat data) {
    if (_waitingHeartbeatResponse) {
      _waitingHeartbeatResponse = false;
    } else {
      send(HeartBeat());
    }
  }

  @override
  Future<void> send<T extends GeneratedMessage>(T data) async {
    if (isAlive) {
      try {
        await queuePacket(PacketBase()
          ..typeName = data.info_.qualifiedMessageName
          ..nonce = nextNonce()
          ..data = data.writeToBuffer());
      } catch (e) {
        close();
      }
    }
  }

  void stopHeartbeat() {
    _heartbeatChecker?.responded();
  }
}
