import time
import threading


"""
Run an action after some time.
Can be overwritten by a new action, which will ignore the previous action
"""


class TimerAction:
    def __init__(self):
        self.thread = None
        self.lock = threading.Lock()  # Lock to ensure thread-safety
        self.callback = None
        self.last_stop = None

    def cancel(self):
        self.thread._stop()

    def fire(self, callback, seconds):
        """
        Run callback after the given seconds, unless cancel() is called
        If the event fires again, cancels the previous action
        """
        self.callback = callback
        self.seconds = seconds

        with self.lock:
            if self.thread and self.thread.is_alive():
                self.last_stop.set()
                self.thread = None
                self.last_stop = None

            stop_event = threading.Event()
            self.last_stop = stop_event
            self.thread = threading.Thread(
                target=self.worker,
                args=(callback, seconds, stop_event)
            )
            self.thread.start()

    def worker(self, callback, seconds, stop_event):
        step = 0.2
        if seconds <= 0.1:
            step = seconds
        if step*2 < seconds:
            step = seconds / 2
        start_time = time.time()

        while time.time() - start_time < seconds:
            time.sleep(step)
            if stop_event.is_set():
                return # Killed

        callback()
