package com.foxx.androidcast.studio;

/*********************************************************************
 * SessionDocument.java
 * Created at: Mon 18 May 2026 18:26:28 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class SessionDocument
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (3 commits, 101 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	56deae476a4589f4802783a7f6f20383897b4fc6d04c153734fa13ffdfe519c1
**********************************************************************/
import org.json.JSONArray;
import org.json.JSONObject;

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

/** Parsed session JSON (aggregate fields + optional time series). */
public final class SessionDocument {
    public final String path;
    public final String direction;
    public final String role;
    public final String transport;
    public final long startedMs;
    public final long durationMs;
    public final List<SamplePoint> samples = new ArrayList<>();

    private SessionDocument(String path, JSONObject root) {
        this.path = path;
        direction = inferDirection(path, root);
        role = root.optString("role", "recv".equals(direction) ? "receiver" : "sender");
        transport = root.optString("transport", "?");
        startedMs = root.optLong("started_at_epoch_ms", 0L);
        durationMs = root.optLong("duration_ms", 0L);
        JSONArray arr = root.optJSONArray("samples");
        if (arr != null) {
            for (int i = 0; i < arr.length(); i++) {
                JSONObject o = arr.optJSONObject(i);
                if (o != null) {
                    samples.add(SamplePoint.fromJson(o));
                }
            }
        }
    }

    public static SessionDocument load(Path file) throws Exception {
        String text = Files.readString(file, StandardCharsets.UTF_8);
        JSONObject root = new JSONObject(text);
        return new SessionDocument(file.getFileName().toString(), root);
    }

    public String title() {
        return path + " (" + direction + ", " + transport + ")";
    }

    private static String inferDirection(String fileName, JSONObject root) {
        String d = root.optString("direction", "");
        if ("send".equals(d) || "recv".equals(d)) {
            return d;
        }
        if (fileName != null) {
            if (fileName.startsWith("session_send_")) {
                return "send";
            }
            if (fileName.startsWith("session_recv_")) {
                return "recv";
            }
        }
        return "receiver".equals(root.optString("role", "")) ? "recv" : "send";
    }

    public static final class SamplePoint {
        public final long tMs;
        public final double videoBitrateKbps;
        public final int rttMs;
        public final double lossRatio;
        public final double encodeFps;
        public final int congestionLevel;

        SamplePoint(long tMs, double videoBitrateKbps, int rttMs, double lossRatio,
                double encodeFps, int congestionLevel) {
            this.tMs = tMs;
            this.videoBitrateKbps = videoBitrateKbps;
            this.rttMs = rttMs;
            this.lossRatio = lossRatio;
            this.encodeFps = encodeFps;
            this.congestionLevel = congestionLevel;
        }

        static SamplePoint fromJson(JSONObject o) {
            return new SamplePoint(
                    o.optLong("t_ms", 0L),
                    o.optDouble("video_bitrate_kbps", 0.0),
                    o.optInt("rtt_ms", 0),
                    o.optDouble("loss_ratio", 0.0),
                    o.optDouble("encode_fps", 0.0),
                    o.optInt("congestion_level", 0));
        }
    }
}
