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

const ResourceCommand = require("resource://devtools/shared/commands/resource/resource-command.js");

module.exports = async function ({
  targetCommand,
  targetFront,
  onAvailableArray,
}) {
  const isBrowserToolbox =
    targetCommand.descriptorFront.isBrowserProcessDescriptor;
  const isNonTopLevelFrameTarget =
    !targetFront.isTopLevel &&
    targetFront.targetType === targetCommand.TYPES.FRAME;

  if (isBrowserToolbox && isNonTopLevelFrameTarget) {
    // In the BrowserToolbox, non-top-level frame targets are already
    // debugged via content-process targets.
    return;
  }

  if (targetFront.isDestroyed()) {
    return;
  }
  const threadFront = await targetFront.getFront("thread");

  let isInterrupted = false;
  const onPausedPacket = packet => {
    // If paused by an explicit interrupt, which are generated by the
    // slow script dialog and internal events such as setting
    // breakpoints, ignore the event.
    const { why } = packet;
    if (why.type === "interrupted" && !why.onNext) {
      isInterrupted = true;
      return;
    }

    // Ignore attached events because they are not useful to the user.
    if (why.type == "alreadyPaused" || why.type == "attached") {
      return;
    }

    const resource = {
      state: "paused",
      why,
      frame: packet.frame,
    };
    onAvailableArray([[ResourceCommand.TYPES.THREAD_STATE, [resource]]]);
  };
  threadFront.on("paused", onPausedPacket);

  threadFront.on("resumed", () => {
    // NOTE: the client suppresses resumed events while interrupted
    // to prevent unintentional behavior.
    // see [client docs](devtools/client/debugger/src/client/README.md#interrupted) for more information.
    if (isInterrupted) {
      isInterrupted = false;
      return;
    }

    const resource = { state: "resumed" };
    onAvailableArray([[ResourceCommand.TYPES.THREAD_STATE, [resource]]]);
  });

  // Notify about already paused thread
  const pausedPacket = threadFront.getLastPausePacket();
  if (pausedPacket) {
    onPausedPacket(pausedPacket);
  }
};
