'use strict';

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

var _regenerator;

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

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 _ramda;

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

var _pMapSeries;

function _load_pMapSeries() {
  return _pMapSeries = _interopRequireDefault(require('p-map-series'));
}

var _removedComponents;

function _load_removedComponents() {
  return _removedComponents = require('../removed-components');
}

var _logger;

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

var _bitId;

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

var _constants;

function _load_constants() {
  return _constants = require('../../constants');
}

var _models;

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

var _component;

function _load_component() {
  return _component = _interopRequireDefault(require('../../consumer/component'));
}

var _scope;

function _load_scope() {
  return _scope = _interopRequireDefault(require('../scope'));
}

var _consumer;

function _load_consumer() {
  return _consumer = require('../../consumer');
}

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

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

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

var RemoveModelComponents = function () {
  function RemoveModelComponents(scope, bitIds, force, removeSameOrigin, consumer) {
    _classCallCheck(this, RemoveModelComponents);

    this.removeSameOrigin = false;

    this.scope = scope;
    this.bitIds = bitIds;
    this.force = force;
    this.removeSameOrigin = removeSameOrigin;
    this.consumer = consumer;
  }

  _createClass(RemoveModelComponents, [{
    key: 'remove',
    value: function () {
      var _ref = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee() {
        var _this = this;

        var _ref2, missingComponents, foundComponents, dependentBits, removedComponents, ids, removedDependencies;

        return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _context.next = 2;
                return this.scope.filterFoundAndMissingComponents(this.bitIds);

              case 2:
                _ref2 = _context.sent;
                missingComponents = _ref2.missingComponents;
                foundComponents = _ref2.foundComponents;
                _context.next = 7;
                return this.scope.findDependentBits(foundComponents);

              case 7:
                dependentBits = _context.sent;

                if (!((_ramda || _load_ramda()).default.isEmpty(dependentBits) || this.force)) {
                  _context.next = 15;
                  break;
                }

                _context.next = 11;
                return (0, (_pMapSeries || _load_pMapSeries()).default)(foundComponents, function (bitId) {
                  return _this._removeSingle(bitId);
                });

              case 11:
                removedComponents = _context.sent;
                ids = new (Function.prototype.bind.apply((_bitId || _load_bitId()).BitIds, [null].concat(_toConsumableArray(removedComponents.map(function (x) {
                  return x.bitId;
                })))))();
                removedDependencies = new (Function.prototype.bind.apply((_bitId || _load_bitId()).BitIds, [null].concat(_toConsumableArray((_ramda || _load_ramda()).default.flatten(removedComponents.map(function (x) {
                  return x.removedDependencies;
                }))))))();
                return _context.abrupt('return', new (_removedComponents || _load_removedComponents()).RemovedObjects({ removedComponentIds: ids, missingComponents, removedDependencies }));

              case 15:
                return _context.abrupt('return', new (_removedComponents || _load_removedComponents()).RemovedObjects({ missingComponents, dependentBits }));

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

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

      return remove;
    }()

    /**
     * removeSingle - remove single component
     * @param {BitId} bitId - list of remote component ids to delete
     * @param {boolean} removeSameOrigin - remove component dependencies from same origin
     */

  }, {
    key: '_removeSingle',
    value: function () {
      var _ref3 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(bitId) {
        var component, consumerComponentToRemove, componentList, dependentBits, removedDependencies, version;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                (_logger || _load_logger()).default.debug(`scope.removeSingle ${bitId.toString()}, remove dependencies: ${this.removeSameOrigin.toString()}`);
                // $FlowFixMe
                _context2.next = 3;
                return this.scope.sources.get(bitId);

              case 3:
                component = _context2.sent.toComponentVersion();
                _context2.next = 6;
                return component.toConsumer(this.scope.objects);

              case 6:
                consumerComponentToRemove = _context2.sent;
                _context2.next = 9;
                return this.scope.objects.listComponents();

              case 9:
                componentList = _context2.sent;
                _context2.next = 12;
                return this.scope.findDependentBits(consumerComponentToRemove.flattenedDependencies, bitId.version !== (_constants || _load_constants()).LATEST_BIT_VERSION);

              case 12:
                dependentBits = _context2.sent;
                _context2.next = 15;
                return this._removeComponentsDependencies(dependentBits, componentList, consumerComponentToRemove, bitId);

              case 15:
                removedDependencies = _context2.sent;
                _context2.next = 18;
                return this._removeComponent(bitId, componentList, false);

              case 18:
                version = Object.keys(component.component.versions).length <= 1 ? (_constants || _load_constants()).LATEST_BIT_VERSION : bitId.version;
                return _context2.abrupt('return', { bitId: bitId.changeVersion(version), removedDependencies });

              case 20:
              case 'end':
                return _context2.stop();
            }
          }
        }, _callee2, this);
      }));

      function _removeSingle(_x) {
        return _ref3.apply(this, arguments);
      }

      return _removeSingle;
    }()
  }, {
    key: '_removeComponentsDependencies',
    value: function () {
      var _ref4 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(dependentBits, componentList, consumerComponentToRemove, bitId) {
        var _this2 = this;

        var removedComponents, removedDependencies;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                removedComponents = consumerComponentToRemove.flattenedDependencies.map(function () {
                  var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(dependencyId) {
                    var dependentsIds, relevantDependents, isNested, componentMap;
                    return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
                      while (1) {
                        switch (_context3.prev = _context3.next) {
                          case 0:
                            dependentsIds = dependentBits[dependencyId.toStringWithoutVersion()];
                            relevantDependents = (_ramda || _load_ramda()).default.reject(function (dependent) {
                              return dependent.isEqual(bitId) || dependent.scope !== dependencyId.scope;
                            }, dependentsIds);
                            isNested = true;

                            if (_this2.consumer) {
                              componentMap = _this2.consumer.bitMap.getComponentIfExist(dependencyId);

                              if (componentMap && componentMap.origin !== (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED) {
                                isNested = false;
                              }
                            }

                            if (!((_ramda || _load_ramda()).default.isEmpty(relevantDependents) && !_this2.bitIds.searchWithoutVersion(dependencyId) && ( // don't delete dependency if it is already deleted as an individual
                            dependencyId.scope !== bitId.scope || _this2.removeSameOrigin) && isNested)) {
                              _context3.next = 8;
                              break;
                            }

                            _context3.next = 7;
                            return _this2._removeComponent(dependencyId, componentList, true);

                          case 7:
                            return _context3.abrupt('return', dependencyId);

                          case 8:
                            return _context3.abrupt('return', null);

                          case 9:
                          case 'end':
                            return _context3.stop();
                        }
                      }
                    }, _callee3, _this2);
                  }));

                  return function (_x6) {
                    return _ref5.apply(this, arguments);
                  };
                }());
                _context4.next = 3;
                return Promise.all(removedComponents);

              case 3:
                removedDependencies = _context4.sent;

                removedDependencies = removedDependencies.filter(function (x) {
                  return !(_ramda || _load_ramda()).default.isNil(x);
                });
                return _context4.abrupt('return', (_bitId || _load_bitId()).BitIds.fromArray(removedDependencies));

              case 6:
              case 'end':
                return _context4.stop();
            }
          }
        }, _callee4, this);
      }));

      function _removeComponentsDependencies(_x2, _x3, _x4, _x5) {
        return _ref4.apply(this, arguments);
      }

      return _removeComponentsDependencies;
    }()
  }, {
    key: '_removeComponent',
    value: function () {
      var _ref6 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5(id, componentList) {
        var removeRefs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
        var symlink;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                symlink = componentList.filter(function (component) {
                  return component instanceof (_models || _load_models()).Symlink && id.isEqualWithoutScopeAndVersion(component.toBitId());
                });
                _context5.next = 3;
                return this.scope.sources.clean(id, removeRefs);

              case 3:
                if ((_ramda || _load_ramda()).default.isEmpty(symlink)) {
                  _context5.next = 6;
                  break;
                }

                _context5.next = 6;
                return this.scope.objects.remove(symlink[0].hash());

              case 6:
              case 'end':
                return _context5.stop();
            }
          }
        }, _callee5, this);
      }));

      function _removeComponent(_x8, _x9) {
        return _ref6.apply(this, arguments);
      }

      return _removeComponent;
    }()
  }]);

  return RemoveModelComponents;
}();

exports.default = RemoveModelComponents;