"use strict";

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

var _store = _interopRequireDefault(require("./store"));

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

/*
 * Copyright 2017-19 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.
 */
// localStorage key; note: the value here holds no meaning, it is a
// historical artifact, at this point
const key = 'openwhisk.history';

class HistoryModel {
  // re: eslint-disable; we don't want to publicize this beyond the
  // core, but still want it accessible within this file; eslint
  // doesn't seem to allow for this, by default.
  // eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
  constructor() {
    this._lines = typeof window !== 'undefined' && JSON.parse((0, _store.default)().getItem(key)) || [];
    this._cursor = this._lines.length; // pointer to historic line
  }
  /** return the given line of history */


  line(idx) {
    return this._lines[idx];
  }

  slice(start, end) {
    return this._lines.slice(start, end);
  }

  get cursor() {
    return this._cursor;
  }
  /** change the cursor, protecting against under- and overflow */


  guardedChange(incr) {
    const newCursor = this._cursor + incr;

    if (newCursor < 0) {
      this._cursor = 0;
    } else if (newCursor > this._lines.length) {
      this._cursor = this._lines.length;
    } else {
      this._cursor = newCursor;
    } // console.log('history::newCursor', cursor, lines.length, lines[cursor])


    return this._cursor;
  }
  /**
   * Clear out all history
   *
   */


  wipe() {
    this._lines = [];
    (0, _store.default)().setItem(key, JSON.stringify(this._lines));
    return true;
  }
  /** add a line of repl history */


  add(line) {
    if (this._lines.length === 0 || JSON.stringify(this._lines[this._lines.length - 1]) !== JSON.stringify(line)) {
      // don't add sequential duplicates
      this._lines.push(line);

      (0, _store.default)().setItem(key, JSON.stringify(this._lines)); // console.log('history::add', cursor)
    }

    this._cursor = this._lines.length;
    return this._cursor - 1;
  }
  /** update a line of repl history -- for async operations */


  update(cursor, updateFn) {
    // console.log('history::update', cursor)
    updateFn(this._lines[cursor]);
    (0, _store.default)().setItem(key, JSON.stringify(this._lines));
  }

  lineByIncr(incr) {
    return this.line(this.guardedChange(incr));
  }
  /** go back one entry */


  previous() {
    return this.lineByIncr(-1);
  }
  /** go forward one entry */


  next() {
    return this.lineByIncr(+1);
  }
  /** return to the oldest entry */


  first() {
    this._cursor = 0;
    return this.line(this._cursor);
  }
  /** return to the newest entry */


  last() {
    this._cursor = this._lines.length - 1;
    return this.line(this.cursor);
  }
  /**
   * Search the history model
   *
   * @param filter a search string, search regexp, or search function
   * @param startIdx if undefined or negative, start from the end, otherwise,
   * search backwards from the given index
   *
   */


  findIndex(filter, startIdx) {
    let filterFn;

    if (typeof filter === 'string') {
      const regexp = new RegExp(filter.replace(/([$.])/g, '\\$1'));

      filterFn = line => regexp.test(line.raw);
    } else if (filter instanceof RegExp) {
      filterFn = line => filter.test(line.raw);
    } else {
      filterFn = filter;
    }

    for (let idx = startIdx !== undefined && startIdx >= 0 ? startIdx : this._lines.length - 1; idx >= 0; idx--) {
      if (filterFn(this._lines[idx])) {
        return idx;
      }
    }
  }
  /**
   * Search the history model
   *
   * @param filter a search string, search regexp, or search function
   *
   */


  find(filter) {
    const idx = this.findIndex(filter);
    return idx !== undefined && this._lines[idx];
  }

} // For now, we have a single global history. We could make this
// per-tab state; see https://github.com/IBM/kui/issues/1299


exports.HistoryModel = HistoryModel;
const History = new HistoryModel();
exports.History = History;
var _default = History;
exports.default = _default;