#!/usr/bin/env python3
"""Cliente DASH real, sin reproducir nada: lee el MPD, baja segmentos y lleva la cuenta del buffer.

La decisión de calidad la toma aquí el cliente, en cada segmento. El servidor solo guarda archivos.

  dash_client.py http://servidor:puerto/video.mpd [fixed|last|ruta/a/abr.py] [--segments N]
"""
import argparse
import sys
import time
import urllib.request
import xml.etree.ElementTree as ET

from dash_sim import BUFFER_MAX_S, fixed_top, last_sample, load_choose

NS = {"mpd": "urn:mpeg:dash:schema:mpd:2011"}


def read_manifest(url):
    """Devuelve (lista de (bitrate, id) ordenada, template, duración de segmento, total)."""
    with urllib.request.urlopen(url, timeout=10) as answer:
        root = ET.fromstring(answer.read())
    adaptation = root.find("mpd:Period/mpd:AdaptationSet", NS)
    template = adaptation.find("mpd:SegmentTemplate", NS)
    duration = int(template.get("duration")) / int(template.get("timescale"))
    total = int(root.get("mediaPresentationDuration")[2:-1])
    reps = sorted((int(rep.get("bandwidth")), rep.get("id"))
                  for rep in adaptation.findall("mpd:Representation", NS))
    return reps, template.get("media"), duration, int(total / duration)


def play(mpd_url, choose, limit=None):
    """Baja todos los segmentos. Imprime una línea por segmento; devuelve los segundos congelados."""
    reps, media, duration, total = read_manifest(mpd_url)
    bitrates = [bitrate for bitrate, _ in reps]
    base = mpd_url.rsplit("/", 1)[0]
    samples = []
    buffer_s = 0.0
    frozen_total = 0.0
    start = time.monotonic()
    print(" seg      t  calidad   medido   buffer  congelado", flush=True)
    for number in range(limit or total):
        if buffer_s > BUFFER_MAX_S - duration:
            pause = buffer_s - (BUFFER_MAX_S - duration)
            time.sleep(pause)
            buffer_s -= pause
        quality = choose(bitrates, list(samples), buffer_s)
        path = media.replace("$RepresentationID$", reps[quality][1]).replace("$Number$", str(number))
        began = time.monotonic()
        with urllib.request.urlopen(f"{base}/{path}", timeout=30) as answer:
            size = len(answer.read())
        took = time.monotonic() - began
        samples.append(size * 8 / took)
        frozen = max(0.0, took - buffer_s) if number > 0 else 0.0
        frozen_total += frozen
        buffer_s = max(0.0, buffer_s - took) + duration
        print(f"{number:4} {time.monotonic() - start:5.1f}s {bitrates[quality] // 1000:6}k "
              f"{samples[-1] / 1e6:6.2f}M {buffer_s:7.1f}s {frozen:8.1f}s", flush=True)
    print(f"congelado total: {frozen_total:.1f} s", flush=True)
    return frozen_total


def main():
    parser = argparse.ArgumentParser(description="Cliente DASH")
    parser.add_argument("url")
    parser.add_argument("strategy", nargs="?", default="last")
    parser.add_argument("--segments", type=int)
    args = parser.parse_args()
    choose = {"fixed": fixed_top, "last": last_sample}.get(args.strategy) or load_choose(args.strategy)
    play(args.url, choose, args.segments)
    return 0


if __name__ == "__main__":
    sys.exit(main())
