from ..print.message import debug as debug
from .common import AbstractBothContextManager as AbstractBothContextManager
from collections.abc import Callable as Callable
from typing import Any

class MeasureTime(AbstractBothContextManager['MeasureTime']):
    ''' Context manager to measure execution time.

\tThis context manager measures the execution time of the code block it wraps
\tand prints the result using a specified print function.

\tArgs:
\t\tprint_func      (Callable): Function to use to print the execution time (e.g. debug, info, warning, error, etc.).
\t\tmessage         (str):      Message to display with the execution time. Defaults to "Execution time".
\t\tperf_counter    (bool):     Whether to use time.perf_counter_ns or time.time_ns. Defaults to True.

\tExamples:
\t\t.. code-block:: python

\t\t\t> import time
\t\t\t> import stouputils as stp
\t\t\t> with stp.MeasureTime(stp.info, message="My operation"):
\t\t\t...     time.sleep(0.5)
\t\t\t> # [INFO HH:MM:SS] My operation: 500.123ms (500123456ns)

\t\t\t> with stp.MeasureTime(): # Uses debug by default
\t\t\t...     time.sleep(0.1)
\t\t\t> # [DEBUG HH:MM:SS] Execution time: 100.456ms (100456789ns)
\t'''
    print_func: Callable[..., None]
    message: str
    perf_counter: bool
    ns: Callable[[], int]
    start_ns: int
    def __init__(self, print_func: Callable[..., None] = ..., message: str = 'Execution time', perf_counter: bool = True) -> None: ...
    def __enter__(self) -> MeasureTime:
        """ Enter context manager, record start time """
    def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
        """ Exit context manager, calculate duration and print """
    async def __aenter__(self) -> MeasureTime:
        """ Enter async context manager, record start time """
    async def __aexit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: Any | None) -> None:
        """ Exit async context manager, calculate duration and print """
