'use strict';

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

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

function _load_minimatch() {
  return _minimatch = _interopRequireDefault(require('minimatch'));
}

var _constants;

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

var _componentMap;

function _load_componentMap() {
  return _componentMap = _interopRequireDefault(require('../../../bit-map/component-map'));
}

var _bitId;

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

var _generalError;

function _load_generalError() {
  return _generalError = _interopRequireDefault(require('../../../../error/general-error'));
}

var _hasWildcard;

function _load_hasWildcard() {
  return _hasWildcard = _interopRequireDefault(require('../../../../utils/string/has-wildcard'));
}

var _consumerOverrides;

function _load_consumerOverrides() {
  return _consumerOverrides = require('../../../config/consumer-overrides');
}

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 OverridesDependencies = function () {
  function OverridesDependencies(component, consumer) {
    _classCallCheck(this, OverridesDependencies);

    this.component = component;
    this.consumer = consumer; // $FlowFixMe
    this.componentMap = this.component.componentMap;
    this.componentFromModel = this.component.componentFromModel;
    this.manuallyRemovedDependencies = {};
    this.manuallyAddedDependencies = {};
  }

  _createClass(OverridesDependencies, [{
    key: 'shouldIgnoreFile',
    value: function shouldIgnoreFile(file, fileType) {
      var shouldIgnoreByGlobMatch = function shouldIgnoreByGlobMatch(patterns) {
        return patterns.some(function (pattern) {
          return (0, (_minimatch || _load_minimatch()).default)(file, pattern);
        });
      };
      var field = fileType.isTestFile ? 'devDependencies' : 'dependencies';
      var ignoreField = this.component.overrides.getIgnoredFiles(field);
      var ignore = shouldIgnoreByGlobMatch(ignoreField);
      if (ignore) {
        this._addManuallyRemovedDep(field, file);
      }
      return ignore;
    }
  }, {
    key: 'shouldIgnorePackage',
    value: function shouldIgnorePackage(packageName, fileType) {
      var shouldIgnorePackage = function shouldIgnorePackage(packages) {
        return packages.some(function (pkg) {
          return pkg === packageName;
        });
      };
      var field = fileType.isTestFile ? 'devDependencies' : 'dependencies';
      var ignoreField = this.component.overrides.getIgnoredPackages(field);
      var ignore = shouldIgnorePackage(ignoreField);
      if (ignore) {
        this._addManuallyRemovedDep(field, packageName);
      }
      return ignore;
    }
  }, {
    key: 'shouldIgnorePeerPackage',
    value: function shouldIgnorePeerPackage(packageName) {
      var shouldIgnorePackage = function shouldIgnorePackage(packages) {
        return packages.some(function (pkg) {
          return pkg === packageName;
        });
      };
      var field = 'peerDependencies';
      var ignorePeer = this.component.overrides.getIgnoredPackages(field);
      var ignore = shouldIgnorePackage(ignorePeer);
      if (ignore) {
        this._addManuallyRemovedDep(field, packageName);
      }
      return ignore;
    }
  }, {
    key: 'shouldIgnoreComponent',
    value: function shouldIgnoreComponent(componentId, fileType) {
      var componentIdStr = componentId.toStringWithoutVersion();
      var shouldIgnore = function shouldIgnore(ids) {
        return ids.some(function (idStr) {
          if ((0, (_hasWildcard || _load_hasWildcard()).default)(idStr)) {
            // we don't support wildcards for components for now. it gets things complicated
            // and may cause unpredicted behavior especially for imported that the originally ignored
            // wildcards interfere with legit components
            return null;
          }
          return componentId.toStringWithoutVersion() === idStr || componentId.toStringWithoutScopeAndVersion() === idStr;
        });
      };
      var field = fileType.isTestFile ? 'devDependencies' : 'dependencies';
      var ignoreField = this.component.overrides.getIgnoredComponents(field);
      var ignore = shouldIgnore(ignoreField);
      if (ignore) {
        this._addManuallyRemovedDep(field, componentIdStr);
      }
      return ignore;
    }
  }, {
    key: 'getDependenciesToAddManually',
    value: function getDependenciesToAddManually(packageJson, existingDependencies) {
      var _this = this;

      var overrides = this.component.overrides.componentOverridesData;
      if (!overrides) return null;
      var idsFromBitmap = this.consumer.bitMap.getAllBitIds([(_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED, (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED]);
      var components = {};
      var packages = {};
      (_consumerOverrides || _load_consumerOverrides()).dependenciesFields.forEach(function (depField) {
        if (!overrides[depField]) return;
        var idsFromModel = _this.componentFromModel ? _this.componentFromModel.dependencies.getAllIds() : new (_bitId || _load_bitId()).BitIds();
        Object.keys(overrides[depField]).forEach(function (dependency) {
          var dependencyValue = overrides[depField][dependency];
          if (dependencyValue === (_constants || _load_constants()).MANUALLY_REMOVE_DEPENDENCY) return;
          var componentId = _this._getComponentIdToAdd(depField, dependency, dependencyValue, idsFromBitmap, idsFromModel);
          if (componentId) {
            // $FlowFixMe
            var dependencyExist = existingDependencies[depField].find(function (d) {
              return d.id.isEqualWithoutScopeAndVersion(componentId);
            });
            if (!dependencyExist) {
              _this._addManuallyAddedDep(depField, componentId.toString());
              components[depField] ? components[depField].push(componentId) : components[depField] = [componentId];
            }
            return;
          }
          var addedPkg = _this._manuallyAddPackage(depField, dependency, dependencyValue, packageJson);
          if (addedPkg) {
            packages[depField] = Object.assign(packages[depField] || {}, addedPkg);
          }
        });
      });
      return { components, packages };
    }
  }, {
    key: '_getComponentIdToAdd',
    value: function _getComponentIdToAdd(field, dependency, dependencyValue, idsFromBitmap, idsFromModel) {
      if (field === 'peerDependencies') return null;
      if (!dependency.startsWith((_constants || _load_constants()).OVERRIDE_COMPONENT_PREFIX)) return null;
      dependency = dependency.replace((_constants || _load_constants()).OVERRIDE_COMPONENT_PREFIX, '');
      var idFromBitMap = idsFromBitmap.searchStrWithoutVersion(dependency) || idsFromBitmap.searchStrWithoutScopeAndVersion(dependency);
      var idFromModel = idsFromModel.searchStrWithoutVersion(dependency) || idsFromModel.searchStrWithoutScopeAndVersion(dependency);
      if (!idFromBitMap && !idFromModel) return null;
      // $FlowFixMe one of them must be set (see one line above)
      var id = idFromModel || idFromBitMap;
      return dependencyValue === (_constants || _load_constants()).MANUALLY_ADD_DEPENDENCY ? id : id.changeVersion(dependencyValue);
    }
  }, {
    key: '_manuallyAddPackage',
    value: function _manuallyAddPackage(field, dependency, dependencyValue, packageJson) {
      var packageVersionToAdd = function packageVersionToAdd() {
        if (dependencyValue !== (_constants || _load_constants()).MANUALLY_ADD_DEPENDENCY) {
          return dependencyValue;
        }
        if (!packageJson) return null;
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;

        try {
          for (var _iterator = (_consumerOverrides || _load_consumerOverrides()).dependenciesFields[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            var depField = _step.value;

            if (packageJson[depField]) {
              var found = Object.keys(packageJson[depField]).find(function (pkg) {
                return pkg === dependency;
              });
              if (found) return packageJson[depField][dependency];
            }
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }

        return null;
      };
      var versionToAdd = packageVersionToAdd();
      if (!versionToAdd) {
        throw new (_generalError || _load_generalError()).default(`unable to manually add the dependency "${dependency}" into "${this.component.id.toString()}".
it's not an existing component, nor existing package`);
      }
      var packageStr = `${dependency}@${versionToAdd}`;
      this._addManuallyAddedDep(field, packageStr);

      return { [dependency]: versionToAdd };
    }
  }, {
    key: '_addManuallyRemovedDep',
    value: function _addManuallyRemovedDep(field, value) {
      this.manuallyRemovedDependencies[field] ? this.manuallyRemovedDependencies[field].push(value) : this.manuallyRemovedDependencies[field] = [value];
    }
  }, {
    key: '_addManuallyAddedDep',
    value: function _addManuallyAddedDep(field, value) {
      this.manuallyAddedDependencies[field] ? this.manuallyAddedDependencies[field].push(value) : this.manuallyAddedDependencies[field] = [value];
    }
  }]);

  return OverridesDependencies;
}();

exports.default = OverridesDependencies;