"use strict";

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

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

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

  _ramda = function () {
    return data;
  };

  return data;
}

function _componentConfig() {
  const data = _interopRequireDefault(require("./component-config"));

  _componentConfig = function () {
    return data;
  };

  return data;
}

function _constants() {
  const data = require("../../constants");

  _constants = function () {
    return data;
  };

  return data;
}

function _consumerOverrides() {
  const data = require("./consumer-overrides");

  _consumerOverrides = function () {
    return data;
  };

  return data;
}

class ComponentOverrides {
  constructor(overrides, overridesFromConsumer) {
    this.overrides = overrides || {};
    this.overridesFromConsumer = overridesFromConsumer || {};
  }
  /**
   * overrides of component can be determined by three different sources.
   * 1. component-config. (bit.json/package.json of the component itself).
   *    authored normally don't have it, most imported have it, unless they choose not to write package.json/bit.json.
   * 2. consumer-config. (bit.json/package.json of the consumer when it has overrides of the component).
   * 3. model. (when the component is tagged, the overrides data is saved into the model).
   *
   * the strategy of loading them is simple:
   * if the component config is written to the filesystem, use it (#1).
   * if the component config is not written, it can be for two reasons:
   * a) it's imported and the user chose not to write package.json nor bit.json. in this case, use
   * component from the model.
   * b) it's author. by default, the config is written into consumer-config (if not exist) on import.
   * which, in this case, use only consumer-config.
   * an exception is when an author runs `eject-conf` command to explicitly write the config, then,
   * use the component-config.
   */


  static loadFromConsumer(overridesFromConsumer, overridesFromModel, componentConfig, isAuthor) {
    if (componentConfig && componentConfig.componentHasWrittenConfig) {
      // $FlowFixMe
      return new ComponentOverrides(componentConfig.overrides, overridesFromConsumer);
    }

    if (!isAuthor) {
      return ComponentOverrides.loadFromScope(overridesFromModel);
    }

    return new ComponentOverrides(overridesFromConsumer, overridesFromConsumer);
  }

  static loadFromScope(overridesFromModel = {}) {
    // $FlowFixMe
    return new ComponentOverrides(_ramda().default.clone(overridesFromModel), {});
  }

  static componentOverridesDataFields() {
    return _consumerOverrides().dependenciesFields;
  }

  get componentOverridesData() {
    const fields = ComponentOverrides.componentOverridesDataFields();

    const isDependencyField = (val, field) => fields.includes(field);

    return _ramda().default.pickBy(isDependencyField, this.overrides);
  }

  getComponentDependenciesWithVersion() {
    const allDeps = Object.assign({}, this.overrides.dependencies, this.overrides.devDependencies, this.overrides.peerDependencies);
    return this._filterForComponentWithValidVersion(allDeps);
  }

  getComponentDependenciesWithVersionFromConsumer() {
    const allDeps = Object.assign({}, this.overridesFromConsumer.dependencies, this.overridesFromConsumer.devDependencies, this.overridesFromConsumer.peerDependencies);
    return this._filterForComponentWithValidVersion(allDeps);
  }

  _filterForComponentWithValidVersion(deps) {
    return Object.keys(deps).reduce((acc, current) => {
      if (this._isValidVersion(deps[current]) && current.startsWith(_constants().OVERRIDE_COMPONENT_PREFIX)) {
        const component = current.replace(_constants().OVERRIDE_COMPONENT_PREFIX, '');
        acc[component] = deps[current];
      }

      return acc;
    }, {});
  }

  _isValidVersion(ver) {
    return ver !== _constants().MANUALLY_ADD_DEPENDENCY && ver !== _constants().MANUALLY_REMOVE_DEPENDENCY;
  }

  getIgnored(field) {
    return _ramda().default.keys(_ramda().default.filter(dep => dep === _constants().MANUALLY_REMOVE_DEPENDENCY, this.overrides[field] || {}));
  }

  getIgnoredFiles(field) {
    const ignoredRules = this.getIgnored(field);
    return ignoredRules.filter(rule => rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)).map(rule => rule.replace(_constants().OVERRIDE_FILE_PREFIX, ''));
  }

  getIgnoredComponents(field) {
    const ignoredRules = this.getIgnored(field);
    return _ramda().default.flatten(ignoredRules.filter(rule => rule.startsWith(_constants().OVERRIDE_COMPONENT_PREFIX)).map(rule => rule.replace(_constants().OVERRIDE_COMPONENT_PREFIX, '')).map(idStr => [idStr, ...this._getComponentNamesFromPackages(idStr)]));
  }
  /**
   * it is possible that a user added the component into the overrides as a package.
   * e.g. `@bit/david.utils.is-string` instead of `@bit/david.utils/is-string`
   * or, if not using bit.dev, `@bit/utils.is-string` instead of `@bit/utils/is-string`
   */


  _getComponentNamesFromPackages(idStr) {
    const idSplitByDot = idStr.split('.');
    const numberOfDots = idSplitByDot.length - 1;
    if (numberOfDots === 0) return []; // nothing to do. it wasn't entered as a package

    const localScopeComponent = idSplitByDot.join('/'); // convert all dots to slashes

    if (numberOfDots === 1) {
      // it can't be from bit.dev, it must be locally
      return [localScopeComponent];
    } // there are two dots or more. it can be from bit.dev and it can be locally
    // for a remoteScopeComponent, leave the first dot and convert only the rest to a slash


    const remoteScopeComponent = `${_ramda().default.head(idSplitByDot)}.${_ramda().default.tail(idSplitByDot).join('/')}`;
    return [localScopeComponent, remoteScopeComponent];
  }

  getIgnoredPackages(field) {
    const ignoredRules = this.getIgnored(field);
    return ignoredRules.filter(rule => !rule.startsWith(_constants().OVERRIDE_FILE_PREFIX) && !rule.startsWith(_constants().OVERRIDE_COMPONENT_PREFIX));
  }

  stripOriginallySharedDir(sharedDir) {
    if (!sharedDir) return;

    _consumerOverrides().dependenciesFields.forEach(field => {
      if (!this.overrides[field]) return;
      Object.keys(this.overrides[field]).forEach(rule => {
        if (!rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)) return;
        const fileWithSharedDir = rule.replace(_constants().OVERRIDE_FILE_PREFIX, ''); // $FlowFixMe we made sure that sharedDir is not empty

        const fileWithoutSharedDir = fileWithSharedDir.replace(`${sharedDir}/`, ''); // $FlowFixMe

        const value = this.overrides[field][rule]; // $FlowFixMe

        delete this.overrides[field][rule]; // $FlowFixMe

        this.overrides[field][`${_constants().OVERRIDE_FILE_PREFIX}${fileWithoutSharedDir}`] = value;
      });
    });
  }

  addOriginallySharedDir(sharedDir) {
    if (!sharedDir) return;

    _consumerOverrides().dependenciesFields.forEach(field => {
      if (!this.overrides[field]) return;
      Object.keys(this.overrides[field]).forEach(rule => {
        if (!rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)) return;
        const fileWithoutSharedDir = rule.replace(_constants().OVERRIDE_FILE_PREFIX, ''); // $FlowFixMe

        const fileWithSharedDir = `${sharedDir}/${fileWithoutSharedDir}`; // $FlowFixMe

        const value = this.overrides[field][rule]; // $FlowFixMe

        delete this.overrides[field][rule]; // $FlowFixMe

        this.overrides[field][`${_constants().OVERRIDE_FILE_PREFIX}${fileWithSharedDir}`] = value;
      });
    });
  }

  static getAllFilesPaths(overrides) {
    if (!overrides) return [];
    const allDeps = Object.assign({}, overrides.dependencies, overrides.devDependencies, overrides.peerDependencies);
    return Object.keys(allDeps).filter(rule => rule.startsWith(_constants().OVERRIDE_FILE_PREFIX)).map(rule => rule.replace(_constants().OVERRIDE_FILE_PREFIX, ''));
  }

  clone() {
    return new ComponentOverrides(_ramda().default.clone(this.overrides), _ramda().default.clone(this.overridesFromConsumer));
  }

}

exports.default = ComponentOverrides;