import sys
from typing import Callable, List

from message import P1A, P2A, PaxosRequest
from paxos_utils import BallotNumber
import threading

"""
Timers for retrying certain operations (e.g. resending messages)
"""


class Timer:
    def __init__(self) -> None:
        pass

    def __str__(self) -> str:
        return f"timer: {self.__class__.__name__}\n"


class ClientTimer(Timer):
    CLIENT_RETRY_MILLIS = 50000

    def __init__(self, request: PaxosRequest, req_num: int) -> None:
        super().__init__()
        self.paxos_req: PaxosRequest = request
        self.req_num: int = req_num


class P2ATimer(Timer):
    P2A_RETRY_MILLIS = 50000

    def __init__(self, p2a: P2A) -> None:
        super().__init__()
        self.p2a: P2A = p2a


class HeartBeatTimer(Timer):
    HEARTBEAT_RETRY_MILLIS = 1000

    def __init__(self) -> None:
        super().__init__()


class HeartBeatCheckTimer(Timer):
    HEARTBEAT_CHECK_RETRY_MILLIS = 5000

    def __init__(self, ballot_num: List[BallotNumber]) -> None:
        super().__init__()
        self.ballot_num: List[BallotNumber] = ballot_num


class LeaderElectionTimer(Timer):
    LEADER_ELECTION_TIMER = 500000

    def __init__(self, p1a: P1A) -> None:
        super().__init__()
        self.p1a: P1A = p1a


"""
Setting a timer with callback
"""


def setTimer(timer: Timer, timerLengthMillis: int, callback: Callable):
    # threading.Timer takes in time (in s), a callback function, and arguments
    # (timer, ) is a list of positional arguments to the callback function
    S = threading.Timer(timerLengthMillis / 1000.0, callback, (timer,))
    S.start()