import asyncio, subprocess, threading, json
from fastapi import FastAPI, WebSocket
from fastapi.responses import FileResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
import cv2

app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")

sample_queue: asyncio.Queue = asyncio.Queue(maxsize=8000)
app.state.capture_proc = None

@app.get("/")
def index():
    return FileResponse("static/index.html")

@app.post("/start_capture")
async def start_capture():
    if getattr(app.state,"capture_proc",None):
        return {"status":"already_running"}

    proc = subprocess.Popen(
        ["/home/pi/AI0/main"],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True,
        bufsize=1
    )
    app.state.capture_proc = proc

    def reader():
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        for line in proc.stdout:
            parts = line.strip().split(',')
            if len(parts)==4:
                sample = {"t":float(parts[0]),"volt":float(parts[1]),
                          "accel_g":float(parts[2]),"accel_mps2":float(parts[3])}
                loop.call_soon_threadsafe(asyncio.create_task, sample_queue.put(sample))
    threading.Thread(target=reader,daemon=True).start()
    return {"status":"started"}

@app.post("/stop_capture")
async def stop_capture():
    proc = getattr(app.state,"capture_proc",None)
    if proc:
        proc.terminate()
        proc.wait()
        app.state.capture_proc = None
    return {"status":"stopped"}

@app.websocket("/ws")
async def websocket_samples(ws:WebSocket):
    await ws.accept()
    try:
        while True:
            sample = await sample_queue.get()
            await ws.send_text(json.dumps({"type":"sample","data":sample}))
    except:
        pass

# 摄像头
CAMERA_INDEX = 0
def gen_frames():
    cap = cv2.VideoCapture(CAMERA_INDEX)
    if not cap.isOpened(): return
    while True:
        success, frame = cap.read()
        if not success: continue
        ret, buf = cv2.imencode('.jpg',frame)
        if not ret: continue
        yield (b'--frame\r\nContent-Type: image/jpeg\r\n\r\n'+buf.tobytes()+b'\r\n')
    cap.release()

@app.get("/video_feed")
def video_feed():
    return StreamingResponse(gen_frames(),media_type='multipart/x-mixed-replace; boundary=frame')
