"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

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

function _bluebird() {
  const data = require("bluebird");

  _bluebird = function () {
    return data;
  };

  return data;
}

function _path() {
  const data = _interopRequireDefault(require("path"));

  _path = function () {
    return data;
  };

  return data;
}

function _fsExtra() {
  const data = _interopRequireDefault(require("fs-extra"));

  _fsExtra = function () {
    return data;
  };

  return data;
}

function _ramda() {
  const data = _interopRequireDefault(require("ramda"));

  _ramda = function () {
    return data;
  };

  return data;
}

function _bitId() {
  const data = _interopRequireDefault(require("../../bit-id/bit-id"));

  _bitId = function () {
    return data;
  };

  return data;
}

function _models() {
  const data = require("../models");

  _models = function () {
    return data;
  };

  return data;
}

function _() {
  const data = require(".");

  _ = function () {
    return data;
  };

  return data;
}

function _logger() {
  const data = _interopRequireDefault(require("../../logger/logger"));

  _logger = function () {
    return data;
  };

  return data;
}

function _invalidIndexJson() {
  const data = _interopRequireDefault(require("../exceptions/invalid-index-json"));

  _invalidIndexJson = function () {
    return data;
  };

  return data;
}

const COMPONENTS_INDEX_FILENAME = 'index.json';

class ComponentsIndex {
  constructor(indexPath, index = []) {
    this.indexPath = indexPath;
    this.index = index;
  }

  static load(basePath) {
    var _this = this;

    return (0, _bluebird().coroutine)(function* () {
      const indexPath = _this._composePath(basePath);

      try {
        const index = yield _fsExtra().default.readJson(indexPath);
        return new ComponentsIndex(indexPath, index);
      } catch (err) {
        if (err.message.includes('Unexpected token')) {
          throw new (_invalidIndexJson().default)(indexPath, err.message);
        }

        throw err;
      }
    })();
  }

  static create(basePath) {
    const indexPath = this._composePath(basePath);

    return new ComponentsIndex(indexPath);
  }

  static reset(basePath) {
    var _this2 = this;

    return (0, _bluebird().coroutine)(function* () {
      const indexPath = _this2._composePath(basePath);

      _logger().default.debug(`ComponentsIndex, deleting the index file at ${indexPath}`);

      yield _fsExtra().default.remove(indexPath);
    })();
  }

  write() {
    var _this3 = this;

    return (0, _bluebird().coroutine)(function* () {
      return _fsExtra().default.writeJson(_this3.indexPath, _this3.index, {
        spaces: 2
      });
    })();
  }

  getIds() {
    return this.index.filter(indexItem => !indexItem.isSymlink).map(indexItem => this.indexItemToBitId(indexItem));
  }

  getIdsIncludesSymlinks() {
    return this.index.map(indexItem => this.indexItemToBitId(indexItem));
  }

  getIdByHash(hash) {
    const foundIndexItem = this.index.find(indexItem => indexItem.hash === hash);
    if (!foundIndexItem) return null;
    return this.indexItemToBitId(foundIndexItem);
  }

  getHashes() {
    return this.index.filter(indexItem => !indexItem.isSymlink).map(indexItem => indexItem.hash);
  }

  getHashesIncludeSymlinks() {
    return this.index.map(indexItem => indexItem.hash);
  }

  indexItemToBitId(indexItem) {
    // $FlowFixMe box is not needed
    return new (_bitId().default)(indexItem.id);
  }

  addMany(bitObjects) {
    const added = bitObjects.map(bitObject => this.addOne(bitObject));
    return added.some(oneAdded => oneAdded); // return true if one of the objects was added
  }

  addOne(bitObject) {
    if (!(bitObject instanceof _models().ModelComponent) && !(bitObject instanceof _models().Symlink)) return false;
    const hash = bitObject.hash().toString();
    if (this._exist(hash)) return false;
    this.index.push({
      id: {
        scope: bitObject.scope || null,
        name: bitObject.name
      },
      isSymlink: bitObject instanceof _models().Symlink,
      hash
    });
    return true;
  }

  removeMany(refs) {
    const removed = refs.map(ref => this.removeOne(ref.toString()));
    return removed.some(removedOne => removedOne); // return true if one of the objects was removed
  }

  removeOne(hash) {
    const found = this._find(hash);

    if (!found) return false;
    this.index = _ramda().default.without([found], this.index);
    return true;
  }

  getPath() {
    return this.indexPath;
  }
  /**
   * it's obviously not accurate. a local path might include 'bithub' as part of the path as well.
   * however, it's needed only for suppressing the error message when the indexJson is outdate,
   * so if it happens on a local scope it's okay.
   * for other purposes, don't rely on this.
   */


  isFileOnBitHub() {
    return this.indexPath.includes('/bithub/');
  }

  _find(hash) {
    return this.index.find(indexItem => indexItem.hash === hash);
  }

  _exist(hash) {
    return Boolean(this._find(hash));
  }

  static _composePath(basePath) {
    return _path().default.join(basePath, COMPONENTS_INDEX_FILENAME);
  }

}

exports.default = ComponentsIndex;