"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _debug = _interopRequireDefault(require("debug"));

var _capabilities = require("../core/capabilities");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/*
 * Copyright 2019 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const debug = (0, _debug.default)('core/models/TabState');
let tabStateConfig;

try {
  tabStateConfig = require('@kui-shell/client/config.d/limits.json');
} catch (err) {
  debug('using default TabStateConfig');
  tabStateConfig = {
    maxWatchersPerTab: 10
  };
}
/**
 * State that we want to keep per tab
 *
 */


class TabState {
  // eslint-disable-next-line no-useless-constructor
  constructor(uuid) {
    this.uuid = uuid;
    /** is the tab ready for command execution? */

    this.ready = false;
    this._ageCounter = 0;
  }

  get env() {
    return this._env;
  }

  get cwd() {
    return this._cwd;
  }

  capture() {
    this._env = Object.assign({}, process.env);
    this._cwd = (0, _capabilities.inBrowser)() ? process.env.PWD : process.cwd().slice(0); // just in case, copy the string

    debug('captured tab state', this.cwd);
  }
  /**
   * @return the number of attached jobs
   */


  get jobs() {
    return !this._jobs ? 0 : this._jobs.filter(_ => _ !== undefined).length;
  }
  /** INTERNAL: abort the oldest job, and return the index of its slot */


  abortOldestJob() {
    const oldestSlot = this._age.reduce((minAgeIdx, age, idx, ages) => {
      if (minAgeIdx === -1) {
        return idx;
      } else if (ages[minAgeIdx] > age) {
        return idx;
      } else {
        return minAgeIdx;
      }
    }, -1);

    this._jobs[oldestSlot].abort();

    return oldestSlot;
  }
  /** INTERNAL: find a free job slot, aborting the oldest job if necessary to free up a slot */


  findFreeJobSlot() {
    const idx = this._jobs.findIndex(_ => _ === undefined);

    if (idx === -1) {
      return this.abortOldestJob();
    } else {
      return idx;
    }
  }
  /** attach a job to this tab */


  captureJob(job) {
    if (!this._jobs) {
      const maxJobs = tabStateConfig.maxWatchersPerTab;
      this._jobs = new Array(maxJobs);
      this._age = new Array(maxJobs);
    }

    const slot = this.findFreeJobSlot();
    this._jobs[slot] = job;
    this._age[slot] = this._ageCounter++;
  }
  /**
   * Abort all jobs attached to this tab
   *
   */


  abortAllJobs() {
    if (this._jobs) {
      this._jobs.forEach((job, idx) => {
        this.abortAt(idx);
      });
    }
  }
  /** INTERNAL: abort the job at the given index */


  abortAt(idx) {
    this._jobs[idx].abort();

    this.clearAt(idx);
  }
  /** INTERNAL: clear the references to the job at the given index */


  clearAt(idx) {
    this._jobs[idx] = undefined;
    this._age[idx] = undefined;
  }
  /**
   * Restore tab state
   *
   */


  restore() {
    process.env = this._env;

    if (this._cwd !== undefined) {
      if ((0, _capabilities.inBrowser)()) {
        debug('changing cwd', process.env.PWD, this._cwd);
        process.env.PWD = this._cwd;
      } else {
        debug('changing cwd', process.cwd(), this._cwd);
        process.chdir(this._cwd);
      }
    }
  }

}

exports.default = TabState;