import win32api, win32process
from typing import Optional


def _set_win_process_priority() -> Optional[bool]:
    """
    Sets the process priority class to an elevated value.

    Microbenchmarks are typically very short in duration and therefore are prone
    to noise from other code running on the same machine. Setting the process priority
    to an elevated level while running the benchmarks helps mitigate that noise
    so the results are more accurate (and also more consistent between runs).

    Returns
    -------
    success : bool, optional
        Indication of whether (or not) setting the process priority class succeeded.
        If the priority did not need to be elevated (because it was already), None is returned.
    """

    # Psuedo-handle for the current process.
    # Because this is a psuedo-handle (i.e. isn't a real handle), it doesn't need to be cleaned up.
    curr_proc_hnd = win32api.GetCurrentProcess()

    # We use the 'ABOVE_NORMAL_PRIORITY_CLASS' here, as that should be good enough to reduce general noise;
    # if necessary, we can try the 'HIGH_PRIORITY_CLASS' but that class and higher can begin to cause the system
    # to become unresponsive so we'll avoid it unless needed; or we can control it with something like a
    # 'strong_hint' bool parameter which chooses between ABOVE_NORMAL_PRIORITY_CLASS and HIGH_PRIORITY.
    target_priority_class: int = win32process.ABOVE_NORMAL_PRIORITY_CLASS

    try:
        # Get the current process priority class. If it's already equal to or higher than the class
        # we were going to set to, don't bother -- we don't want to lower it.
        current_priority_class = win32process.GetPriorityClass(curr_proc_hnd)
        if current_priority_class >= target_priority_class:
            return None

        else:
            # Try to set the priority level for the current process.
            # It can fail if the user (or process) hasn't been granted the PROCESS_SET_INFORMATION right.
            # https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass
            return win32process.SetPriorityClass(curr_proc_hnd, target_priority_class)
    except:
        return False