#!/usr/bin/env python3
from http.server import ThreadingHTTPServer,SimpleHTTPRequestHandler
from pathlib import Path
import json,os,socket,threading,webbrowser,subprocess
R=Path(__file__).resolve().parent; os.chdir(R); S=R/"state.json"
class H(SimpleHTTPRequestHandler):
 def end_headers(self):
  self.send_header("Cache-Control","no-store, no-cache, must-revalidate"); super().end_headers()
 def do_GET(self):
  if self.path.startswith("/api/state"):
   b=S.read_bytes(); self.send_response(200); self.send_header("Content-Type","application/json; charset=utf-8"); self.send_header("Content-Length",str(len(b))); self.end_headers(); self.wfile.write(b); return
  super().do_GET()
 def do_POST(self):
  n=int(self.headers.get("Content-Length","0"))
  try: x=json.loads(self.rfile.read(n) or b"{}")
  except: self.send_error(400); return
  if self.path=="/api/tts":
   text=str(x.get("text","")).strip()[:500]
   rate=max(90,min(260,int(x.get("rate",155))))
   voice=str(x.get("voice","Kyoko"))
   if text:
    # Native macOS Japanese speech. No browser autoplay restriction.
    try: subprocess.Popen(["say","-v",voice,"-r",str(rate),text])
    except: subprocess.Popen(["say","-r",str(rate),text])
   self.send_response(204); self.end_headers(); return
  if self.path=="/api/chime":
   try: subprocess.Popen(["afplay",str(R/"audio"/"chime.mp3")])
   except Exception: pass
   self.send_response(204); self.end_headers(); return
  if self.path=="/api/full":
   text=str(x.get("text","")).strip()[:500]
   rate=max(90,min(260,int(x.get("rate",150))))
   voice=str(x.get("voice","Kyoko"))
   def run_full():
    try: subprocess.run(["afplay",str(R/"audio"/"chime.mp3")])
    except Exception: pass
    import time; time.sleep(0.65)
    if text:
     try: subprocess.run(["say","-v",voice,"-r",str(rate),text])
     except Exception: subprocess.run(["say","-r",str(rate),text])
   threading.Thread(target=run_full,daemon=True).start()
   self.send_response(204); self.end_headers(); return
  if self.path=="/api/state":
   s=json.loads(S.read_text(encoding="utf-8")); s.update(x); s["rev"]=int(s.get("rev",0))+1
   S.write_text(json.dumps(s,ensure_ascii=False),encoding="utf-8"); self.send_response(204); self.end_headers(); return
  self.send_error(404)
def ip():
 s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
 try:s.connect(("8.8.8.8",80));return s.getsockname()[0]
 except:return"localhost"
 finally:s.close()
if __name__=="__main__":
 print("\nN700 REAL DISPLAY V10.1")
 print("PC表示 : http://localhost:8961/display.html?v=101")
 print("iPhone : http://%s:8961/control.html?v=101\n"%ip())
 threading.Timer(1,lambda:webbrowser.open("http://localhost:8961/display.html?v=101")).start()
 ThreadingHTTPServer(("0.0.0.0",8961),H).serve_forever()
