"""Utilities for the CI."""

import os
from datetime import datetime, timedelta
from functools import wraps
from typing import Any, Callable, Dict, TypedDict, TypeVar, Union


class DirectoryExcursion:
    def __init__(self, path: Union[os.PathLike, str]) -> None:
        self.path = path
        self.curdir = os.path.normpath(os.path.abspath(os.path.curdir))

    def __enter__(self) -> None:
        os.chdir(self.path)

    def __exit__(self, *args: Any) -> None:
        os.chdir(self.curdir)


R = TypeVar("R")


def cd(path: Union[os.PathLike, str]) -> Callable:
    """Decorator for changing directory temporarily."""

    def chdir(func: Callable[..., R]) -> Callable[..., R]:
        @wraps(func)
        def inner(*args: Any, **kwargs: Any) -> R:
            with DirectoryExcursion(path):
                return func(*args, **kwargs)

        return inner

    return chdir


Record = TypedDict("Record", {"count": int, "total": timedelta})
timer: Dict[str, Record] = {}


def record_time(func: Callable[..., R]) -> Callable[..., R]:
    """Decorator for recording function runtime."""
    global timer

    @wraps(func)
    def inner(*args: Any, **kwargs: Any) -> R:
        if func.__name__ not in timer:
            timer[func.__name__] = {"count": 0, "total": timedelta(0)}
        s = datetime.now()
        try:
            r = func(*args, **kwargs)
        finally:
            e = datetime.now()
            timer[func.__name__]["count"] += 1
            timer[func.__name__]["total"] += e - s
        return r

    return inner


def print_time() -> None:
    """Print all recorded items by :py:func:`record_time`."""
    global timer
    for k, v in timer.items():
        print(
            "Name:",
            k,
            "Called:",
            v["count"],
            "Elapsed:",
            f"{v['total'].seconds} secs",
        )


ROOT = os.path.normpath(
    os.path.join(
        os.path.dirname(os.path.abspath(__file__)), os.path.pardir, os.path.pardir
    )
)
R_PACKAGE = os.path.join(ROOT, "R-package")
JVM_PACKAGES = os.path.join(ROOT, "jvm-packages")
PY_PACKAGE = os.path.join(ROOT, "python-package")

"""Utilities for the CI."""
import os
from datetime import datetime, timedelta
from functools import wraps
from typing import Any, Callable, Dict, TypedDict, TypeVar, Union


class DirectoryExcursion:
    def __init__(self, path: Union[os.PathLike, str]) -> None:
        self.path = path
        self.curdir = os.path.normpath(os.path.abspath(os.path.curdir))

    def __enter__(self) -> None:
        os.chdir(self.path)

    def __exit__(self, *args: Any) -> None:
        os.chdir(self.curdir)


R = TypeVar("R")


def cd(path: Union[os.PathLike, str]) -> Callable:
    """Decorator for changing directory temporarily."""

    def chdir(func: Callable[..., R]) -> Callable[..., R]:
        @wraps(func)
        def inner(*args: Any, **kwargs: Any) -> R:
            with DirectoryExcursion(path):
                return func(*args, **kwargs)

        return inner

    return chdir


Record = TypedDict("Record", {"count": int, "total": timedelta})
timer: Dict[str, Record] = {}


def record_time(func: Callable[..., R]) -> Callable[..., R]:
    """Decorator for recording function runtime."""
    global timer

    @wraps(func)
    def inner(*args: Any, **kwargs: Any) -> R:
        if func.__name__ not in timer:
            timer[func.__name__] = {"count": 0, "total": timedelta(0)}
        s = datetime.now()
        try:
            r = func(*args, **kwargs)
        finally:
            e = datetime.now()
            timer[func.__name__]["count"] += 1
            timer[func.__name__]["total"] += e - s
        return r

    return inner


def print_time() -> None:
    """Print all recorded items by :py:func:`record_time`."""
    global timer
    for k, v in timer.items():
        print(
            "Name:",
            k,
            "Called:",
            v["count"],
            "Elapsed:",
            f"{v['total'].seconds} secs",
        )


ROOT = os.path.normpath(
    os.path.join(
        os.path.dirname(os.path.abspath(__file__)), os.path.pardir, os.path.pardir
    )
)
R_PACKAGE = os.path.join(ROOT, "R-package")
JVM_PACKAGES = os.path.join(ROOT, "jvm-packages")
PY_PACKAGE = os.path.join(ROOT, "python-package")
