import subprocess, threading, time, textwrap
from PIL import Image, ImageDraw, ImageFont
class Recorder:
    def __init__(self,out,side,sha):
        self.out=out; self.side=side; self.sha=sha; self.lines=[]; self.lock=threading.Lock(); self.stop=False
        self.font=ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf',18)
        self.title=ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf',23)
        self.log=open(out/'capture-encoder.log','w')
        self.proc=subprocess.Popen(['ffmpeg','-y','-hide_banner','-loglevel','error','-f','rawvideo','-pixel_format','rgb24','-video_size','1600x1000','-framerate','5','-i','pipe:0','-c:v','libx264','-preset','ultrafast','-crf','20','-pix_fmt','yuv420p',str(out/(side+'.mp4'))],stdin=subprocess.PIPE,stderr=self.log)
        self.worker=threading.Thread(target=self.record); self.worker.start()
    def write(self,text):
        with self.lock:
            for line in text.splitlines():
                self.lines.extend(textwrap.wrap(line,136,replace_whitespace=False,drop_whitespace=False) or [''])
            self.lines.append('')
    def frame(self):
        im=Image.new('RGB',(1600,1000),'#10141b'); d=ImageDraw.Draw(im)
        d.text((28,18),f'{self.side.upper()} | Live CLI capture | {self.sha[:12]}',font=self.title,fill='#f1f4f8')
        d.text((28,58),'Linux • real T3 server • synthetic git project • Replay multi-turn • 1600 × 1000',font=self.font,fill='#9eaec1')
        d.line((28,93,1572,93),fill='#455165')
        with self.lock: lines=list(self.lines[-35:])
        for n,line in enumerate(lines):
            color='#8dd9ef' if line.startswith('$') else '#e3eaf2'
            if 'exit 1' in line or '"status": "failed"' in line or "Couldn't recreate" in line: color='#ffb6ac'
            d.text((28,111+24*n),line,font=self.font,fill=color)
        d.text((28,968),'Actual command output; paths redacted. Thread-show and runs display selected fields.',font=self.font,fill='#9eaec1')
        return im
    def record(self):
        while not self.stop:
            start=time.monotonic(); self.proc.stdin.write(self.frame().tobytes()); time.sleep(max(0,.2-(time.monotonic()-start)))
    def finish(self):
        time.sleep(1)
        a=self.frame(); time.sleep(.5); b=self.frame()
        assert a.tobytes()==b.tobytes()
        b.save(self.out/(self.side+'.png'))
        time.sleep(3); self.stop=True; self.worker.join(); self.proc.stdin.close(); self.proc.wait(); self.log.close()
