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

class LegacyProcessesWatcher {
  constructor(targetCommand, onTargetAvailable, onTargetDestroyed) {
    this.targetCommand = targetCommand;
    this.rootFront = targetCommand.rootFront;

    this.onTargetAvailable = onTargetAvailable;
    this.onTargetDestroyed = onTargetDestroyed;

    this.descriptors = new Set();
    this._processListChanged = this._processListChanged.bind(this);
  }

  async _processListChanged() {
    if (this.targetCommand.isDestroyed()) {
      return;
    }

    const processes = await this.rootFront.listProcesses();
    // Process the new list to detect the ones being destroyed
    // Force destroyed the descriptor as well as the target
    for (const descriptor of this.descriptors) {
      if (!processes.includes(descriptor)) {
        // Manually call onTargetDestroyed listeners in order to
        // ensure calling them *before* destroying the descriptor.
        // Otherwise the descriptor will automatically destroy the target
        // and may not fire the contentProcessTarget's destroy event.
        const target = descriptor.getCachedTarget();
        if (target) {
          this.onTargetDestroyed(target);
        }

        descriptor.destroy();
        this.descriptors.delete(descriptor);
      }
    }

    const promises = processes
      .filter(descriptor => !this.descriptors.has(descriptor))
      .map(async descriptor => {
        // Add the new process descriptors to the local list
        this.descriptors.add(descriptor);
        const target = await descriptor.getTarget();
        if (!target) {
          console.error(
            "Wasn't able to retrieve the target for",
            descriptor.actorID
          );
          return;
        }
        await this.onTargetAvailable(target);
      });

    await Promise.all(promises);
  }

  async listen() {
    this.rootFront.on("processListChanged", this._processListChanged);
    await this._processListChanged();
  }

  unlisten() {
    this.rootFront.off("processListChanged", this._processListChanged);
  }
}

module.exports = LegacyProcessesWatcher;
