from collections.abc import Iterator
from contextlib import contextmanager

import dagster_shared.seven as seven

import dagster._check as check


class TimerResult:
    start_time: float
    end_time: float | None

    def __init__(self):
        self.start_time = seven.time_fn()
        self.end_time = None

    @property
    def seconds(self) -> float:
        if self.end_time is None:
            check.failed("end time is not set")
        return self.end_time - self.start_time

    @property
    def millis(self) -> float:
        return self.seconds * 1000


@contextmanager
def time_execution_scope() -> Iterator[TimerResult]:
    """Context manager that times the execution of a block of code.

    Example:
    ..code-block::
        from solid_util.timing import time_execution_scope
        with time_execution_scope() as timer_result:
            do_some_operation()

        print(
            'do_some_operation took {timer_result.millis} milliseconds'.format(
                timer_result=timer_result
            )
        )
    """
    timer_result = TimerResult()
    yield timer_result
    timer_result.end_time = seven.time_fn()
