import os
import re
import shlex
import shutil
import time

from wox.constants import DOT_WOX


def auto_clean_logs():
    """
        Setting up logging for wox is bound to create a log file. When
        wox crash before the session starts, the log file is empty and
        pollutes the wox session log directory.

        To mitigate this flaw from logging, this function will remove
        the last log file created.
    """

    logs_dir = DOT_WOX / '.logs'

    list_of_files = list(logs_dir.glob('**/output*'))

    if list_of_files:
        latest_file = max(list_of_files, key=os.path.getctime)
        os.remove(latest_file)

def normalize_python_version(digits):
    """
        Ensures correct major.minor version scheme for Python 3 (e.g. 36 => 3.6).

        Parameters
        ----------
        digits: str

        Returns
        -------
        str
    """

    return f'{digits[0]}.{digits[1:]}'

def get_python_version_from_command(command):
    if isinstance(command, str):
        command = shlex.split(command)

    python_interpreter = command[0]

    if python_interpreter == 'py':
        version = re.findall(r'\d+', ' '.join(command))
        version = '.'.join(version)
    else:
        version = re.sub(r'[a-zA-Z]', '', python_interpreter)

    return version

def sort_set(set, iterable):
    """
        Sorts the set with order from original iterable.

        Returns
        -------
        list
    """

    return [element for element in iterable if element in set]

def format_duration(duration):
    """
        Format a duration in seconds into an ISO-like time string
        (e.g. 10 seconds => 00:00:10.XXX).

        Parameters
        ----------
        duration : float
            Duration in seconds.

        Returns
        -------
        str

        Notes
        -----
        This function uses ``divmod()`` to progressively extract hours, minutes and
        seconds from the total duration. ``divmod(a, b)`` returns a tuple
        ``(quotient, remainder)``, equivalent to ``(a // b, a % b)``.

        Examples
        --------
        Both implementations return 1 hour and 71.527 seconds:

        >>> divmod(3671.527, 3600)
        (1.0, 71.527)

        This is equivalent to:
        >>> hours = 3671.527 // 3600
        >>> remainder = 3671.527 % 3600
        >>> (hours, remainder)
        (1.0, 71.527)
    """

    hours, remaining_seconds = divmod(duration, 3600)
    minutes, remaining_seconds = divmod(remaining_seconds, 60)
    seconds = int(remaining_seconds)
    milliseconds = int((remaining_seconds - seconds) * 1000)

    return f'{int(hours):02d}:{int(minutes):02d}:{seconds:02d}.{milliseconds:03d}'

def rmtree_with_retry(path, retries = 5, delay = 0.2):
    """
        Safety layer around shutil.rmtree ensuring the deletion of virtual environment.

        Parameters
        ----------
        path : str
            Path to the virtual environment.
        retries : int
        delay : float

        Raises
        ------
        PermissionError
            shutil.rmtree was not authorized to delete the arborescence.
    """

    for attempt in range(retries):
        try:
            shutil.rmtree(path)
            return
        except PermissionError:
            if attempt + 1 == retries:
                raise
            time.sleep(delay)
