"""
Stimulus player back-end — presents a study's stimuli in the browser (image, text,
survey, website) and pushes onset/offset LSL markers so everything stays event-locked
and is captured by a concurrent recording. Survey/website responses are saved per
participant and flow into the statistical export.

The `Presenter` owns a Markers LSL outlet identical to `StimulusMarkers`, so when you
Record + Present together the markers land in the same session as the sensors.
"""

from __future__ import annotations

import json
import threading
import time
from pathlib import Path


class Presenter:
    """Holds a live Markers LSL outlet for the duration of a presentation."""

    def __init__(self):
        self._lock = threading.Lock()
        self._outlet = None
        self.running = False
        self.participant = None

    def start(self, participant: dict | None = None) -> dict:
        with self._lock:
            if not self.running:
                from pylsl import StreamOutlet
                from ..stimulus.study import MARKER_SPEC
                self._outlet = StreamOutlet(MARKER_SPEC.to_lsl())
                self.running = True
            self.participant = participant or {}
            return {"running": True}

    def marker(self, label: str) -> None:
        from pylsl import local_clock
        with self._lock:
            if self._outlet is not None:
                self._outlet.push_sample([label], local_clock())

    def stop(self) -> dict:
        with self._lock:
            self._outlet = None
            self.running = False
            return {"running": False}


# --------------------------------------------------------------------------
# response storage
# --------------------------------------------------------------------------
def _responses_path(data_dir) -> Path:
    return Path(data_dir) / "responses.json"


def save_response(data_dir, participant: str, stimulus: str, kind: str, payload: dict):
    p = _responses_path(data_dir)
    rows = load_responses(data_dir)
    rows.append({"participant": participant or "", "stimulus": stimulus, "kind": kind,
                 "ts": time.strftime("%Y-%m-%dT%H:%M:%S"), "data": payload})
    json.dump(rows, open(p, "w"), indent=2)


def load_responses(data_dir) -> list:
    p = _responses_path(data_dir)
    if p.exists():
        try:
            return json.load(open(p))
        except Exception:
            return []
    return []


def flatten_trials(plan) -> list[dict]:
    """Flatten a StudyPlan to presentable trial dicts the player steps through."""
    from ..studybuilder.survey import render_questions
    trials = []
    for b in plan.blocks:
        for leaf in b.leaves():
            tr = {"name": leaf.name, "kind": leaf.kind, "text": leaf.text,
                  "image": leaf.image, "duration": leaf.duration, "isi": leaf.isi,
                  "advance": leaf.advance, "props": leaf.props or {}}
            if leaf.kind == "survey":
                qs = (leaf.props or {}).get("questions", [])
                tr["survey_html"] = render_questions(qs)
            if leaf.kind == "website":
                tr["url"] = (leaf.props or {}).get("url", leaf.image or "")
            trials.append(tr)
    return trials
