/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

/**
 * Tests that the Picture-in-Picture toggle is hidden when videos
 * are laid out with dimensions smaller than MIN_VIDEO_DIMENSION (a
 * constant that is also defined in videocontrols.js).
 */
add_task(async () => {
  // Most of the Picture-in-Picture tests run with the always-show
  // preference set to true to avoid the toggle visibility heuristics.
  // Since this test actually exercises those heuristics, we have
  // to temporarily disable that pref.
  //
  // We also reduce the minimum video length for displaying the toggle
  // to 5 seconds to avoid having to include or generate a 45 second long
  // video (which is the default minimum length).
  await SpecialPowers.pushPrefEnv({
    set: [
      [
        "media.videocontrols.picture-in-picture.video-toggle.always-show",
        false,
      ],
      ["media.videocontrols.picture-in-picture.video-toggle.min-video-secs", 5],
    ],
  });

  // This is the minimum size of the video in either width or height for
  // which we will show the toggle. See videocontrols.js.
  const MIN_VIDEO_DIMENSION = 140; // pixels

  for (let videoID of ["with-controls", "no-controls"]) {
    info(`Testing ${videoID} case.`);

    await BrowserTestUtils.withNewTab(
      {
        url: TEST_PAGE_WITH_SOUND,
        gBrowser,
      },
      async browser => {
        // Shrink the video down to less than MIN_VIDEO_DIMENSION.
        let targetWidth = MIN_VIDEO_DIMENSION - 1;
        await SpecialPowers.spawn(
          browser,
          [videoID, targetWidth],
          async (videoID, targetWidth) => {
            let video = content.document.getElementById(videoID);
            let shadowRoot = video.openOrClosedShadowRoot;
            let resizePromise = ContentTaskUtils.waitForEvent(
              shadowRoot.firstChild,
              "resizevideocontrols"
            );
            video.style.width = targetWidth + "px";
            await resizePromise;
          }
        );

        // The toggle should be hidden.
        await testToggleHelper(browser, videoID, false);

        // Now re-expand the video.
        await SpecialPowers.spawn(browser, [videoID], async videoID => {
          let video = content.document.getElementById(videoID);
          let shadowRoot = video.openOrClosedShadowRoot;
          let resizePromise = ContentTaskUtils.waitForEvent(
            shadowRoot.firstChild,
            "resizevideocontrols"
          );
          video.style.width = "";
          await resizePromise;
        });

        // The toggle should be visible.
        await testToggleHelper(browser, videoID, true);
      }
    );
  }
});

/**
 * Tests that when using the experimental toggle variations, videos
 * under 320px width are given the "small-video" attribute.
 */
add_task(async () => {
  const TOGGLE_SMALL = {
    rootID: "pictureInPictureToggle",
    stages: {
      hoverVideo: {
        opacities: {
          ".pip-wrapper": DEFAULT_TOGGLE_OPACITY,
        },
        hidden: [],
      },

      hoverToggle: {
        opacities: {
          ".pip-wrapper": 1.0,
        },
        hidden: [".pip-expanded"],
      },
    },
  };

  const TOGGLE_LARGE = {
    rootID: "pictureInPictureToggle",
    stages: {
      hoverVideo: {
        opacities: {
          ".pip-small": 0.0,
          ".pip-wrapper": DEFAULT_TOGGLE_OPACITY,
          ".pip-expanded": 0.0,
        },
        hidden: [".pip-explainer", ".pip-icon-label > .pip-icon"],
      },
      hoverToggle: {
        opacities: {
          ".pip-small": 0.0,
          ".pip-wrapper": 1.0,
        },
        hidden: [
          ".pip-explainer",
          ".pip-icon-label > .pip-icon",
          ".pip-expanded",
        ],
      },
    },
  };

  // Most of the Picture-in-Picture tests run with the always-show
  // preference set to true to avoid the toggle visibility heuristics.
  // Since this test actually exercises those heuristics, we have
  // to temporarily disable that pref.
  //
  // We also reduce the minimum video length for displaying the toggle
  // to 5 seconds to avoid having to include or generate a 45 second long
  // video (which is the default minimum length).
  await SpecialPowers.pushPrefEnv({
    set: [
      [
        "media.videocontrols.picture-in-picture.video-toggle.always-show",
        false,
      ],
      ["media.videocontrols.picture-in-picture.video-toggle.min-video-secs", 5],
      ["media.videocontrols.picture-in-picture.video-toggle.mode", 1],
    ],
  });

  // Videos that are thinner than MIN_VIDEO_WIDTH should have the small-video
  // attribute set on the experimental toggle.
  const MIN_VIDEO_WIDTH = 320; // pixels

  for (let videoID of ["with-controls", "no-controls"]) {
    info(`Testing ${videoID} case.`);

    await BrowserTestUtils.withNewTab(
      {
        url: TEST_PAGE_WITH_SOUND,
        gBrowser,
      },
      async browser => {
        // Shrink the video down to less than MIN_VIDEO_WIDTH.
        let targetWidth = MIN_VIDEO_WIDTH - 1;
        let isSmallVideo = await SpecialPowers.spawn(
          browser,
          [videoID, targetWidth],
          async (videoID, targetWidth) => {
            let video = content.document.getElementById(videoID);
            let shadowRoot = video.openOrClosedShadowRoot;
            let resizePromise = ContentTaskUtils.waitForEvent(
              shadowRoot.firstChild,
              "resizevideocontrols"
            );
            video.style.width = targetWidth + "px";
            await resizePromise;
            let toggle = shadowRoot.getElementById("pictureInPictureToggle");
            return toggle.hasAttribute("small-video");
          }
        );

        Assert.ok(isSmallVideo, "Video should have small-video attribute");

        await testToggleHelper(browser, videoID, true, undefined, TOGGLE_SMALL);

        // Now re-expand the video.
        isSmallVideo = await SpecialPowers.spawn(
          browser,
          [videoID],
          async videoID => {
            let video = content.document.getElementById(videoID);
            let shadowRoot = video.openOrClosedShadowRoot;
            let resizePromise = ContentTaskUtils.waitForEvent(
              shadowRoot.firstChild,
              "resizevideocontrols"
            );
            video.style.width = "";
            await resizePromise;
            let toggle = shadowRoot.getElementById("pictureInPictureToggle");
            return toggle.hasAttribute("small-video");
          }
        );

        Assert.ok(!isSmallVideo, "Video should not have small-video attribute");

        await testToggleHelper(browser, videoID, true, undefined, TOGGLE_LARGE);
      }
    );
  }
});
