# progress.py

import time
from threading import Event, Thread

from .axicontroller import AxiController


def _progress_sampler(
    stop_event: Event,
    ad_ref: AxiController,
    is_resume: bool,
    start_time: float,
    update_plot_state,
    get_existing_total,
):
    while not stop_event.is_set():
        total_mm = float(ad_ref.plot_status.progress.total or 0.0)
        current_mm = 25.4 * (
            ad_ref.plot_status.stats.down_travel_inch + ad_ref.plot_status.stats.up_travel_inch
        )
        if not is_resume and total_mm > 0.0:
            if (time.time() - start_time) < 2.0 and current_mm > (total_mm * 0.95):
                update_plot_state(total_mm=total_mm)
                stop_event.wait(0.5)
                continue
        existing_total = get_existing_total()
        update_plot_state(progress_mm=current_mm, total_mm=total_mm if total_mm > 0.0 else existing_total)
        stop_event.wait(0.5)


def run_with_progress(
    plot_ad: AxiController,
    run_callable,
    *,
    is_resume: bool,
    update_plot_state,
    get_existing_total,
):
    stop_event = Event()
    start_time = time.time()
    sampler = Thread(
        target=_progress_sampler,
        args=(stop_event, plot_ad, is_resume, start_time, update_plot_state, get_existing_total),
        daemon=True,
    )
    sampler.start()
    try:
        return run_callable()
    finally:
        stop_event.set()
        sampler.join(timeout=1.0)
