'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _regenerator;

function _load_regenerator() {
  return _regenerator = _interopRequireDefault(require('babel-runtime/regenerator'));
}

var _bluebird;

function _load_bluebird() {
  return _bluebird = require('bluebird');
}

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _path;

function _load_path() {
  return _path = _interopRequireDefault(require('path'));
}

var _fsExtra;

function _load_fsExtra() {
  return _fsExtra = _interopRequireDefault(require('fs-extra'));
}

var _ramda;

function _load_ramda() {
  return _ramda = _interopRequireDefault(require('ramda'));
}

var _bitId;

function _load_bitId() {
  return _bitId = _interopRequireDefault(require('../../bit-id/bit-id'));
}

var _models;

function _load_models() {
  return _models = require('../models');
}

var _;

function _load_() {
  return _ = require('.');
}

var _logger;

function _load_logger() {
  return _logger = _interopRequireDefault(require('../../logger/logger'));
}

var _invalidIndexJson;

function _load_invalidIndexJson() {
  return _invalidIndexJson = _interopRequireDefault(require('../exceptions/invalid-index-json'));
}

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

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var COMPONENTS_INDEX_FILENAME = 'index.json';

var ComponentsIndex = function () {
  function ComponentsIndex(indexPath) {
    var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];

    _classCallCheck(this, ComponentsIndex);

    this.indexPath = indexPath;
    this.index = index;
  }

  _createClass(ComponentsIndex, [{
    key: 'write',
    value: function () {
      var _ref = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee() {
        return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                return _context.abrupt('return', (_fsExtra || _load_fsExtra()).default.writeJson(this.indexPath, this.index, { spaces: 2 }));

              case 1:
              case 'end':
                return _context.stop();
            }
          }
        }, _callee, this);
      }));

      function write() {
        return _ref.apply(this, arguments);
      }

      return write;
    }()
  }, {
    key: 'getIds',
    value: function getIds() {
      var _this = this;

      return this.index.filter(function (indexItem) {
        return !indexItem.isSymlink;
      }).map(function (indexItem) {
        return _this.indexItemToBitId(indexItem);
      });
    }
  }, {
    key: 'getIdsIncludesSymlinks',
    value: function getIdsIncludesSymlinks() {
      var _this2 = this;

      return this.index.map(function (indexItem) {
        return _this2.indexItemToBitId(indexItem);
      });
    }
  }, {
    key: 'getIdByHash',
    value: function getIdByHash(hash) {
      var foundIndexItem = this.index.find(function (indexItem) {
        return indexItem.hash === hash;
      });
      if (!foundIndexItem) return null;
      return this.indexItemToBitId(foundIndexItem);
    }
  }, {
    key: 'getHashes',
    value: function getHashes() {
      return this.index.filter(function (indexItem) {
        return !indexItem.isSymlink;
      }).map(function (indexItem) {
        return indexItem.hash;
      });
    }
  }, {
    key: 'getHashesIncludeSymlinks',
    value: function getHashesIncludeSymlinks() {
      return this.index.map(function (indexItem) {
        return indexItem.hash;
      });
    }
  }, {
    key: 'indexItemToBitId',
    value: function indexItemToBitId(indexItem) {
      // $FlowFixMe box is not needed
      return new (_bitId || _load_bitId()).default(indexItem.id);
    }
  }, {
    key: 'addMany',
    value: function addMany(bitObjects) {
      var _this3 = this;

      var added = bitObjects.map(function (bitObject) {
        return _this3.addOne(bitObject);
      });
      return added.some(function (oneAdded) {
        return oneAdded;
      }); // return true if one of the objects was added
    }
  }, {
    key: 'addOne',
    value: function addOne(bitObject) {
      if (!(bitObject instanceof (_models || _load_models()).ModelComponent) && !(bitObject instanceof (_models || _load_models()).Symlink)) return false;
      var 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 || _load_models()).Symlink,
        hash
      });
      return true;
    }
  }, {
    key: 'removeMany',
    value: function removeMany(refs) {
      var _this4 = this;

      var removed = refs.map(function (ref) {
        return _this4.removeOne(ref.toString());
      });
      return removed.some(function (removedOne) {
        return removedOne;
      }); // return true if one of the objects was removed
    }
  }, {
    key: 'removeOne',
    value: function removeOne(hash) {
      var found = this._find(hash);
      if (!found) return false;
      this.index = (_ramda || _load_ramda()).default.without([found], this.index);
      return true;
    }
  }, {
    key: 'getPath',
    value: function 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.
     */

  }, {
    key: 'isFileOnBitHub',
    value: function isFileOnBitHub() {
      return this.indexPath.includes('/bithub/');
    }
  }, {
    key: '_find',
    value: function _find(hash) {
      return this.index.find(function (indexItem) {
        return indexItem.hash === hash;
      });
    }
  }, {
    key: '_exist',
    value: function _exist(hash) {
      return Boolean(this._find(hash));
    }
  }], [{
    key: 'load',
    value: function () {
      var _ref2 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(basePath) {
        var indexPath, index;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                indexPath = this._composePath(basePath);
                _context2.prev = 1;
                _context2.next = 4;
                return (_fsExtra || _load_fsExtra()).default.readJson(indexPath);

              case 4:
                index = _context2.sent;
                return _context2.abrupt('return', new ComponentsIndex(indexPath, index));

              case 8:
                _context2.prev = 8;
                _context2.t0 = _context2['catch'](1);

                if (!_context2.t0.message.includes('Unexpected token')) {
                  _context2.next = 12;
                  break;
                }

                throw new (_invalidIndexJson || _load_invalidIndexJson()).default(indexPath, _context2.t0.message);

              case 12:
                throw _context2.t0;

              case 13:
              case 'end':
                return _context2.stop();
            }
          }
        }, _callee2, this, [[1, 8]]);
      }));

      function load(_x2) {
        return _ref2.apply(this, arguments);
      }

      return load;
    }()
  }, {
    key: 'create',
    value: function create(basePath) {
      var indexPath = this._composePath(basePath);
      return new ComponentsIndex(indexPath);
    }
  }, {
    key: 'reset',
    value: function () {
      var _ref3 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(basePath) {
        var indexPath;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                indexPath = this._composePath(basePath);

                (_logger || _load_logger()).default.debug(`ComponentsIndex, deleting the index file at ${indexPath}`);
                _context3.next = 4;
                return (_fsExtra || _load_fsExtra()).default.remove(indexPath);

              case 4:
              case 'end':
                return _context3.stop();
            }
          }
        }, _callee3, this);
      }));

      function reset(_x3) {
        return _ref3.apply(this, arguments);
      }

      return reset;
    }()
  }, {
    key: '_composePath',
    value: function _composePath(basePath) {
      return (_path || _load_path()).default.join(basePath, COMPONENTS_INDEX_FILENAME);
    }
  }]);

  return ComponentsIndex;
}();

exports.default = ComponentsIndex;