/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

/**
 * Bug 1956165 - Fix picture-in-picture mode on Mobile YouTube
 *
 * YouTube does not play well with our picture in picture implementation, and
 * effectively cancels it. We can work around this conflict with this site patch.
 */

if (!window.__firefoxPiPFix) {
  Object.defineProperty(window, "__firefoxPiPFix", {
    configurable: false,
    value: true,
  });

  console.info(
    "exitFullscreen and window.outerWidth|Height have been overridden for compatibility reasons. See https://bugzilla.mozilla.org/show_bug.cgi?id=1956165 for details."
  );

  const outerWidthDesc = Object.getOwnPropertyDescriptor(window, "outerWidth");
  const outerHeightDesc = Object.getOwnPropertyDescriptor(
    window,
    "outerHeight"
  );
  const originalOuterWidth = outerWidthDesc.get;
  const originalOuterHeight = outerHeightDesc.get;

  // This is the logic YouTube uses to detect the app backgrounding to enter picture in picture mode mode (as of May 28 2025).

  const getRatio = (() => {
    let cachedRatio;
    return function () {
      if (cachedRatio === undefined) {
        const cfg = window.ytcfg.get("WEB_PLAYER_CONTEXT_CONFIGS");
        const experiment =
          cfg?.WEB_PLAYER_CONTEXT_CONFIG_ID_MWEB_WATCH?.serializedExperimentFlags?.match(
            /html5_picture_in_picture_logging_onresize_ratio=(\d+(\.\d+)?)/
          )?.[1];
        cachedRatio = parseFloat(experiment) || 0.33;
      }
      return cachedRatio;
    };
  })();

  const inPipMode = (() => {
    let o_ = 0;
    return function () {
      const l = window.screen.width * window.screen.height;
      const M = originalOuterWidth() * originalOuterHeight();
      o_ = Math.max(o_, l, M);
      return M / o_ < getRatio();
    };
  })();

  outerWidthDesc.get = function () {
    if (inPipMode()) {
      return screen.width;
    }
    return originalOuterWidth();
  };
  outerHeightDesc.get = () => {
    if (inPipMode()) {
      return screen.height;
    }
    return originalOuterHeight();
  };
  Object.defineProperty(window, "outerWidth", outerWidthDesc);
  Object.defineProperty(window, "outerHeight", outerHeightDesc);

  const originalExitFullscreen = window.Document.prototype.exitFullscreen;

  const newExitFullscreen = function () {
    if (inPipMode()) {
      return undefined;
    }
    return originalExitFullscreen.apply(this);
  };

  Object.defineProperty(window.Document.prototype, "exitFullscreen", {
    value: newExitFullscreen,
    writable: true,
    configurable: true,
  });
}
