package com.foxx.androidcast;

/*********************************************************************
 * CastResolution.java
 * Created at: Fri 15 May 2026 16:49:02 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class CastResolution
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (6 commits, 87 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	447a38e8faae8e49ab2215056114497ba9f1d65c0a117a91582865661d7c3687
**********************************************************************/
import android.content.Context;
import android.util.DisplayMetrics;

import com.foxx.androidcast.network.control.NetworkStatsSnapshot;
import com.foxx.androidcast.sender.calibration.CalibrationSourceDimensions;

/** Computes encoder VirtualDisplay size from display metrics and user settings. */
public final class CastResolution {
    private CastResolution() {}

    public static final class Size {
        public final int width;
        public final int height;
        public final int densityDpi;

        public Size(int width, int height, int densityDpi) {
            this.width = width;
            this.height = height;
            this.densityDpi = densityDpi;
        }
    }

    public static Size compute(DisplayMetrics display, CastSettings settings) {
        return compute(display, settings, null);
    }

    public static Size compute(DisplayMetrics display, CastSettings settings, NetworkStatsSnapshot peer) {
        int displayW = display.widthPixels & ~1;
        int displayH = display.heightPixels & ~1;
        float scale = settings.getResolutionScale();
        int encW = even(Math.max(2, (int) (displayW * scale)));
        int encH = even(Math.max(2, (int) (displayH * scale)));

        CastTuningEngine.CaptureLimits limits = CastTuningEngine.resolveCaptureLimits(settings, peer);
        int maxH = limits.maxHeight > 0 ? limits.maxHeight : settings.getMaxHeight();
        int maxW = limits.maxWidth > 0 ? limits.maxWidth : settings.getMaxWidth();

        if (maxH > 0 && maxW == 0) {
            int[] capped = capLongEdge(encW, encH, maxH);
            encW = capped[0];
            encH = capped[1];
        } else {
            if (maxH > 0 && encH > maxH) {
                float ratio = (float) maxH / encH;
                encH = even(maxH);
                encW = even(Math.max(2, (int) (encW * ratio)));
            }
            if (maxW > 0 && encW > maxW) {
                float ratio = (float) maxW / encW;
                encW = even(maxW);
                encH = even(Math.max(2, (int) (encH * ratio)));
            }
        }

        int density = Math.max(120, (int) (display.densityDpi * scale));
        return new Size(encW, encH, density);
    }

    /** Caps the longer side (orientation-independent 720p height-cap mode). */
    private static int[] capLongEdge(int width, int height, int maxLong) {
        int longEdge = Math.max(width, height);
        if (longEdge <= maxLong) {
            return new int[] {width, height};
        }
        float ratio = (float) maxLong / longEdge;
        return new int[] {even(Math.max(2, (int) (width * ratio))),
                even(Math.max(2, (int) (height * ratio)))};
    }

    private static int even(int v) {
        return Math.max(2, v & ~1);
    }

    /** Calibration encoder size from chart asset intrinsic dimensions. */
    public static Size calibrationTestSize(Context context) {
        return CalibrationSourceDimensions.resolve(context);
    }
}
