#!/usr/bin/env python3
"""
Detecta Layout A (tela cheia) vs Layout B (canto direito + compartilhamento)
Amostragem a cada 10s. 1280x720 fonte.

Heurística:
- Layout A: Borrello ocupa > 50% da área da imagem — alta variação de cor/luminância no centro
- Layout B: canto direito (x>800) tem faixa com face/variação; lado esquerdo tem fundo uniforme de compartilhamento

Estratégia simplificada sem OpenCV:
1. Extrai frame como PPM via ffmpeg pipe
2. Divide em 4 quadrantes (TL, TR, BL, BR)
3. Computa stddev de luminância por quadrante
4. Se o quadrante TR (top-right) tem luminância MUITO diferente dos outros 3 → Layout B
5. Caso contrário → Layout A

Também verifica se há faixa preta/overlay de streaming no Layout B.
"""

import subprocess
import struct
import math
import json
import sys
import os

VIDEO = "/opt/mia/workspace/videos/borrello_lives/Feng Shui - Metafisica nos Imóveis.mp4"
OUTPUT = "/opt/mia/workspace/videos/borrello_lives/cortes_feng_shui/layout_timeline.json"
DURATION = 6664
STEP = 10  # segundos entre amostras

W, H = 1280, 720

def extract_frame_rgb(ts):
    """Extrai frame como lista de pixels (r,g,b) via ffmpeg rawvideo."""
    cmd = [
        "ffmpeg", "-ss", str(ts), "-i", VIDEO,
        "-vframes", "1", "-f", "rawvideo",
        "-pix_fmt", "rgb24", "-vf", f"scale={W}:{H}",
        "-loglevel", "quiet", "pipe:1"
    ]
    proc = subprocess.run(cmd, capture_output=True, timeout=15)
    raw = proc.stdout
    expected = W * H * 3
    if len(raw) < expected:
        return None
    return raw[:expected]

def region_stats(raw, x0, y0, x1, y1):
    """Retorna (mean_lum, stddev_lum) da região (x0,y0)-(x1,y1)."""
    pixels = []
    for y in range(y0, y1):
        row_start = y * W * 3
        for x in range(x0, x1):
            idx = row_start + x * 3
            r = raw[idx]
            g = raw[idx+1]
            b = raw[idx+2]
            lum = 0.299*r + 0.587*g + 0.114*b
            pixels.append(lum)
    if not pixels:
        return 0, 0
    n = len(pixels)
    mean = sum(pixels) / n
    variance = sum((p - mean)**2 for p in pixels) / n
    return mean, math.sqrt(variance)

def classify_frame(raw):
    """
    Retorna 'A' ou 'B' com score de confiança.
    
    Layout B heurística:
    - Borrello fica num quadrante no canto direito-inferior ou direito-central
    - Região esquerda (x < 700) tem gradiente de slide (alta variação horizontal)
    - Região direita (x > 900, y > 200) tem rosto com skin tone
    
    Divisões:
    - left_region: x 0-700, y 0-720 (tela compartilhada no layout B)
    - right_region: x 850-1280, y 150-720 (face Borrello no layout B)
    - center_region: x 300-980, y 50-650 (área principal do rosto no layout A)
    """
    # Amostragem em grid reduzido para velocidade (pegar 1 de cada 4 pixels)
    # Região esquerda - tela compartilhada
    left_mean, left_std = region_stats(raw, 0, 0, 700, 720)
    # Região direita - janelinha do Borrello
    right_mean, right_std = region_stats(raw, 850, 150, 1280, 720)
    # Centro - rosto full screen
    center_mean, center_std = region_stats(raw, 250, 50, 1030, 670)
    # Canto direito pequeno
    corner_mean, corner_std = region_stats(raw, 950, 50, 1280, 400)
    # Faixa superior central
    top_mean, top_std = region_stats(raw, 200, 0, 1080, 150)
    
    # Layout B: a região esquerda tem conteúdo de slide (mean != muito escura, std moderada)
    # e a região direita-superior tem um box pequeno (o rosto)
    # Indicador forte de Layout B: diferença grande entre corner_std e center_std
    # com corner mais vivo (não é fundo igual)
    
    # Heurística principal:
    # No Layout A: o centro tem alto stddev (rosto diverso), e left e right são similares
    # No Layout B: left (slide) tem stddev médio, corner (face pequena) tem stddev médio,
    #   mas center stddev pode ser similar — o discriminante melhor é que
    #   a RAZÃO entre left_mean e right_mean numa tela compartilhada tende a 
    #   ser mais uniforme (slide tem cores planas), enquanto no Layout A o fundo
    #   é escuro e o rosto é central.
    
    # Checagem adicional: no Layout B tipicamente há uma linha de divisão vertical
    # entre 700-900 px onde a luminância muda bruscamente.
    # Vamos checar a variacao na faixa vertical x=750-850
    mid_left_mean, mid_left_std = region_stats(raw, 700, 100, 760, 620)
    mid_right_mean, mid_right_std = region_stats(raw, 820, 100, 880, 620)
    
    mid_diff = abs(mid_left_mean - mid_right_mean)
    
    # Scores
    score_B = 0
    reasons = []
    
    # 1. Gradiente na divisao vertical (Layout B tem separacao clara)
    if mid_diff > 30:
        score_B += 2
        reasons.append(f"mid_diff={mid_diff:.1f}>30")
    
    # 2. Regiao esquerda clara (slide branco/colorido) + canto direito mais escuro/diferente
    if left_mean > 100 and abs(left_mean - corner_mean) > 40:
        score_B += 2
        reasons.append(f"slide_left={left_mean:.0f} corner={corner_mean:.0f}")
    
    # 3. Center_std baixo sugere que o rosto nao domina o centro (ele esta no canto)
    # No Layout A o centro tem stddev alto por causa do rosto vs fundo
    if center_std < 40 and left_std > 20:
        score_B += 1
        reasons.append(f"center_std={center_std:.1f}<40")
    
    # 4. Top region clara (slide geralmente tem header) 
    if top_mean > 150:
        score_B += 1
        reasons.append(f"top_mean={top_mean:.0f}>150")
    
    layout = "B" if score_B >= 3 else "A"
    confidence = min(score_B / 5.0, 1.0)
    
    return layout, confidence, {
        "left_mean": round(left_mean, 1), "left_std": round(left_std, 1),
        "right_mean": round(right_mean, 1), "right_std": round(right_std, 1),
        "center_std": round(center_std, 1),
        "corner_mean": round(corner_mean, 1),
        "mid_diff": round(mid_diff, 1),
        "top_mean": round(top_mean, 1),
        "score_B": score_B,
        "reasons": reasons
    }

samples = []
print(f"Analisando {DURATION//STEP} frames (1 a cada {STEP}s)...", flush=True)

for ts in range(0, DURATION, STEP):
    raw = extract_frame_rgb(ts)
    if raw is None:
        layout, conf, meta = "A", 0.5, {"error": "frame_failed"}
    else:
        layout, conf, meta = classify_frame(raw)
    
    samples.append({"ts": ts, "layout": layout, "confidence": round(conf, 2), "meta": meta})
    
    if ts % 120 == 0:
        h = ts // 3600
        m = (ts % 3600) // 60
        s = ts % 60
        print(f"  {h:02d}:{m:02d}:{s:02d} → Layout {layout} (score_B={meta.get('score_B', '?')})", flush=True)

# Consolida em intervalos contíguos
intervals = []
if samples:
    cur_layout = samples[0]["layout"]
    cur_start = 0
    
    for i in range(1, len(samples)):
        if samples[i]["layout"] != cur_layout:
            intervals.append({
                "start": cur_start,
                "end": samples[i]["ts"],
                "layout": cur_layout,
                "duration": samples[i]["ts"] - cur_start
            })
            cur_layout = samples[i]["layout"]
            cur_start = samples[i]["ts"]
    
    # último intervalo
    intervals.append({
        "start": cur_start,
        "end": DURATION,
        "layout": cur_layout,
        "duration": DURATION - cur_start
    })

# Suavização: intervalos < 20s provavelmente são ruído — absorve no vizinho
smoothed = []
for i, iv in enumerate(intervals):
    if iv["duration"] < 20 and i > 0 and smoothed:
        smoothed[-1]["end"] = iv["end"]
        smoothed[-1]["duration"] = smoothed[-1]["end"] - smoothed[-1]["start"]
    else:
        smoothed.append(dict(iv))

result = {
    "samples": samples,
    "intervals_raw": intervals,
    "intervals": smoothed
}

with open(OUTPUT, "w") as f:
    json.dump(result, f, ensure_ascii=False, indent=2)

print(f"\nSalvo: {OUTPUT}", flush=True)
print(f"Intervalos detectados ({len(smoothed)}):", flush=True)
for iv in smoothed:
    h0, m0, s0 = iv["start"]//3600, (iv["start"]%3600)//60, iv["start"]%60
    h1, m1, s1 = iv["end"]//3600, (iv["end"]%3600)//60, iv["end"]%60
    print(f"  [{h0:02d}:{m0:02d}:{s0:02d} - {h1:02d}:{m1:02d}:{s1:02d}] LAYOUT_{iv['layout']} ({iv['duration']}s)", flush=True)
