from queue import Queue


class IntervalTaskMaster ():
    def __init__(self, socketio):
        self.socketio = socketio
        self.tasks_by_id = {}
        self.tasks_id = 0
        self.queue = Queue()

    def start (self):
        self.socketio.start_background_task(self.background_task)
        
    def background_task(self):
        st = 0
        while True:
            # print (f"IntervalTaskMaster is running with {len(self.tasks_by_id)} pending tasks")
            # Add any items in the queue
            while not self.queue.empty():
                task_id, callback, time, interval = self.queue.get()
                print (f"CREATING TASK {task_id} interval:{interval}")
                self.tasks_by_id[task_id] = Task(task_id, callback, time, interval)
            
            remove_intervals = []
            for task_id, task in self.tasks_by_id.items():
                print (f"servicing task {task_id}")
                ran_task = task.service(st)
                if not task.interval and ran_task:
                    remove_intervals.append(task_id)
            for task_id in remove_intervals:
                print (f"deleting task {task_id}")
                del self.tasks_by_id[task_id]
            st = self.calc_current_sleep_time_ms()
            # print (f"taskmaster sleeping {st}")
            self.socketio.sleep(st/1000)

    def calc_current_sleep_time_ms(self):
        min_time = None
        for task in self.tasks_by_id.values():
            if min_time == None or task.time < min_time:
                min_time = task.time
        if min_time is None:
            return 1000
        else:
            return min(10000, min_time / 2)

    def setTimeout (self, callback, time, interval=False):
        task_id = self.tasks_id
        self.tasks_id += 1
        self.queue.put((task_id, callback, time, interval))
        return task_id

    def clearTimeout (self, task_id):
        try:
            del self.tasks_by_id[task_id]
            return True
        except KeyError:
            pass

    def setInterval(self, callback, time):
        return self.setTimeout(callback, time, True)
    
    def clearInterval(self, task_id):
        return self.clearTimeout(task_id)

class Task ():
    def __init__(self, task_id, callback, time, interval=False):
        self.task_id = task_id
        self.callback = callback
        self.time = time
        self.interval = interval
        self.current_timer = time

    def service (self, elapsed_time):
        self.current_timer -= elapsed_time
        if self.current_timer <= 0:
            self.current_timer = 0
            self.callback()
            return True
