package com.foxx.androidcast.ui;

/*********************************************************************
 * ZoomPanContainer.java
 * Created at: Sat 16 May 2026 13:35:48 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class ZoomPanContainer
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (2 commits, 141 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	3523d1adb91e9e2aec52eb364dbdf270f96518c07dcc3f421787da5c3ebb9b3d
**********************************************************************/
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.FrameLayout;

/**
 * Pinch-zoom (5% steps) and two-finger pan over video content.
 * Reports zoom deviation from 100% via {@link OnZoomChangedListener}.
 */
public class ZoomPanContainer extends FrameLayout {
    public interface OnZoomChangedListener {
        void onZoomPercentChanged(int zoomPercent);
    }

    private static final float STEP = 0.05f;
    private static final float MIN_SCALE = 0.50f;
    private static final float MAX_SCALE = 3.00f;

    private float scale = 1f;
    private float panX;
    private float panY;
    private OnZoomChangedListener zoomListener;

    private final ScaleGestureDetector scaleDetector;
    private final GestureDetector panDetector;
    private float lastSpan = -1f;

    public ZoomPanContainer(Context context) {
        this(context, null);
    }

    public ZoomPanContainer(Context context, AttributeSet attrs) {
        super(context, attrs);
        scaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        panDetector = new GestureDetector(context, new PanListener());
    }

    public void setOnZoomChangedListener(OnZoomChangedListener listener) {
        this.zoomListener = listener;
    }

    public void resetTransform() {
        scale = 1f;
        panX = 0f;
        panY = 0f;
        applyTransform();
        notifyZoom();
    }

    public int getZoomPercent() {
        return Math.round((scale - 1f) * 100f);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean scaled = scaleDetector.onTouchEvent(event);
        boolean panned = panDetector.onTouchEvent(event);
        if (event.getActionMasked() == MotionEvent.ACTION_UP
                || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
            lastSpan = -1f;
        }
        return scaled || panned || super.onTouchEvent(event);
    }

    private final class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float span = detector.getCurrentSpan();
            if (lastSpan < 0) {
                lastSpan = span;
                return true;
            }
            float ratio = span / lastSpan;
            lastSpan = span;
            if (ratio > 1.02f) {
                applyStep(1f + STEP);
            } else if (ratio < 0.98f) {
                applyStep(1f - STEP);
            }
            return true;
        }
    }

    private void applyStep(float factor) {
        float target = scale * factor;
        target = Math.max(MIN_SCALE, Math.min(MAX_SCALE, target));
        int quantized = Math.round(target * 20f);
        scale = quantized / 20f;
        applyTransform();
        notifyZoom();
    }

    private final class PanListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if (e1 == null || e2 == null || e2.getPointerCount() < 2) {
                return false;
            }
            panX -= distanceX;
            panY -= distanceY;
            applyTransform();
            return true;
        }
    }

    private void applyTransform() {
        if (getChildCount() == 0) {
            return;
        }
        android.view.View child = getChildAt(0);
        child.setPivotX(child.getWidth() / 2f);
        child.setPivotY(child.getHeight() / 2f);
        child.setScaleX(scale);
        child.setScaleY(scale);
        child.setTranslationX(panX);
        child.setTranslationY(panY);
    }

    private void notifyZoom() {
        if (zoomListener != null) {
            zoomListener.onZoomPercentChanged(getZoomPercent());
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        applyTransform();
    }
}
