"""Dibuja el gráfico tiempo-secuencia de una captura, como el de Wireshark.

    python3 timeseq.py captures/loss-a.pcap captures/loss-a.png

Cada punto es un segmento de datos del cliente. Los retransmitidos van en rojo, y la línea
gris es el último ACK recibido. Wireshark: Statistics > TCP Stream Graphs > Time Sequence.
"""
import sys

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt

from pcaptools import read_capture


def points(segments):
    """Separa los segmentos en datos nuevos, retransmitidos y ACK: (tiempo, MB)."""
    client = (segments[0].src, segments[0].sport)
    new, resent, acks = [], [], []
    for segment in segments:
        if (segment.src, segment.sport) == client:
            if segment.len:
                (resent if segment.resent else new).append((segment.time, segment.seq / 1e6))
        elif segment.has_ack:
            acks.append((segment.time, segment.ack / 1e6))
    return new, resent, acks


def main():
    if len(sys.argv) != 3:
        print(__doc__)
        return 2
    new, resent, acks = points(read_capture(sys.argv[1]))
    figure, axes = plt.subplots(figsize=(8, 4.5))
    if acks:
        axes.step(*zip(*acks), where="post", color="0.6", linewidth=1, label="último ACK")
    if new:
        axes.scatter(*zip(*new), s=4, color="tab:blue", label="datos")
    if resent:
        axes.scatter(*zip(*resent), s=18, color="tab:red", marker="x", label="retransmitidos")
    axes.set_xlabel("tiempo (s)")
    axes.set_ylabel("número de secuencia relativo (MB)")
    axes.legend(loc="upper left")
    figure.tight_layout()
    figure.savefig(sys.argv[2], dpi=130)
    print(f"gráfico en {sys.argv[2]}")
    return 0


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