/* 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";

/* import-globals-from ../../mochitest/role.js */
loadScripts({ name: "role.js", dir: MOCHITESTS_DIR });

const REORDER = { expected: [[EVENT_REORDER, "container"]] };

// Dynamically inserted slotted accessible elements should be in
// the accessible tree.
const snippet = `
<script>
customElements.define("x-el", class extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML =
      "<div role='presentation'><slot></slot></div>";
  }
});
</script>
<x-el id="container" role="group"><label id="l1">label1</label></x-el>
`;

addAccessibleTask(snippet, async function (browser, accDoc) {
  let container = findAccessibleChildByID(accDoc, "container");

  testChildrenIds(container, ["l1"]);

  await contentSpawnMutation(browser, REORDER, function () {
    let labelEl = content.document.createElement("label");
    labelEl.id = "l2";

    let containerEl = content.document.getElementById("container");
    containerEl.appendChild(labelEl);
  });

  testChildrenIds(container, ["l1", "l2"]);
});

// Dynamically inserted not accessible custom element containing an accessible
// in its shadow DOM.
const snippet2 = `
<script>
customElements.define("x-el2", class extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = "<input id='input'>";
  }
});
</script>
<div role="group" id="container"></div>
`;

addAccessibleTask(snippet2, async function (browser, accDoc) {
  let container = findAccessibleChildByID(accDoc, "container");

  await contentSpawnMutation(browser, REORDER, function () {
    content.document.getElementById("container").innerHTML = "<x-el2></x-el2>";
  });

  testChildrenIds(container, ["input"]);
});

/**
 * Ensure that changing the slot on the body while moving the body doesn't
 * try to remove the DocAccessible. We test this here instead of in
 * accessible/tests/mochitest/treeupdate/test_shadow_slots.html because this
 * messes with the body element and we don't want that to impact other tests.
 */
addAccessibleTask(
  `<div id="host"></div>`,
  async function (browser, docAcc) {
    info("Moving body and setting slot on body");
    let reordered = waitForEvent(EVENT_REORDER, docAcc);
    await invokeContentTask(browser, [], () => {
      const host = content.document.getElementById("host");
      const emptyScript = content.document.getElementById("emptyScript");
      const body = content.document.body;
      emptyScript.append(host);
      host.append(body);
      body.slot = "";
    });
    await reordered;
    is(docAcc.childCount, 0, "document has no children after body move");
  },
  {
    chrome: true,
    topLevel: true,
    iframe: true,
    remoteIframe: true,
    contentSetup: async function contentSetup() {
      const doc = content.document;
      const host = doc.getElementById("host");
      host.attachShadow({ mode: "open" });
      const emptyScript = doc.createElement("script");
      emptyScript.id = "emptyScript";
      doc.head.append(emptyScript);
    },
  }
);

addAccessibleTask(
  `
    <marquee id="container"><span><button>Help</button></span></marquee>
  `,
  async function (browser, docAcc) {
    info("A slotted inline");
    const container = findAccessibleChildByID(docAcc, "container");

    testAccessibleTree(container, {
      TEXT_CONTAINER: [{ TEXT_CONTAINER: [{ PUSHBUTTON: { name: "Help" } }] }],
    });

    const SLOT_REORDER = {
      expected: [
        [
          EVENT_REORDER,
          evt => getAccessibleDOMNodeID(evt.accessible.parent) == "container",
        ],
      ],
    };
    await contentSpawnMutation(browser, SLOT_REORDER, function () {
      content.document.getElementById("container").firstElementChild.slot =
        "foo";
    });

    testAccessibleTree(container, {
      TEXT_CONTAINER: [{ TEXT_CONTAINER: [] }],
    });
  }
);
