from typing import Any, Dict, List, Optional, Tuple, Union

import multiprocessing
import queue

__all__ = ["read_queue"]


def read_queue(
    queue_: multiprocessing.Queue,
) -> List[Dict[str, Union[str, bool, int, float, List, Dict, Tuple]]]:
    stack = []
    while True:
        try:
            return_value = queue_.get(timeout=1)
        except queue.Empty:
            break

        # Check if there is a special placeholder value which tells us that
        # we don't have to wait until the queue times out in order to
        # retrieve the final value!
        if "final_queue_element" in return_value:
            del return_value["final_queue_element"]
            do_break = True
        else:
            do_break = False
        stack.append(return_value)
        if do_break:
            break

    if len(stack) == 0:
        raise queue.Empty
    else:
        return stack


def empty_queue(queue_: multiprocessing.Queue) -> None:
    while True:
        try:
            queue_.get(block=False)
        except queue.Empty:
            break

    queue_.close()


def extract_learning_curve(
    stack: List[Dict[str, Any]], key: Optional[str] = None
) -> List[float]:
    learning_curve = []
    for entry in stack:
        if key:
            learning_curve.append(entry["additional_run_info"][key])
        else:
            learning_curve.append(entry["loss"])
    return list(learning_curve)
