'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getManipulateDirWhenImportingComponents = exports.getManipulateDirForExistingComponents = undefined;

var _regenerator;

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

var _bluebird;

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

/**
 * use this method when loading an existing component. don't use it during the import process
 */
var getManipulateDirForExistingComponents = exports.getManipulateDirForExistingComponents = function () {
  var _ref = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(consumer, componentVersion) {
    var id, manipulateDirData, componentMap, version, originallySharedDir, wrapDir, dependencies;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            id = componentVersion.id;
            manipulateDirData = [];
            // in case this is a dependency that was installed via NPM, the file is in the scope but not on
            // the filesystem, in that case, no need for wrapDir or sharedDir

            componentMap = consumer.bitMap.getComponentIfExist(id, { ignoreVersion: true });
            _context.next = 5;
            return componentVersion.getVersion(consumer.scope.objects);

          case 5:
            version = _context.sent;
            originallySharedDir = componentMap ? getOriginallySharedDirIfNeeded(componentMap.origin, version) : null;
            wrapDir = componentMap ? getWrapDirIfNeeded(componentMap.origin, version) : null;

            manipulateDirData.push({ id, originallySharedDir, wrapDir });
            dependencies = version.getAllDependencies();

            dependencies.forEach(function (dependency) {
              var depComponentMap = getDependencyComponentMap(consumer.bitMap, dependency.id);
              var manipulateDirDep = {
                id: dependency.id,
                originallySharedDir: depComponentMap ? depComponentMap.originallySharedDir : null,
                wrapDir: depComponentMap ? depComponentMap.wrapDir : null
              };
              manipulateDirData.push(manipulateDirDep);
            });
            return _context.abrupt('return', manipulateDirData);

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

  return function getManipulateDirForExistingComponents(_x, _x2) {
    return _ref.apply(this, arguments);
  };
}();

/**
 * a dependency might be imported with a different version.
 * e.g. is-string@0.0.1 has a dependency is-type@0.0.1, however is-type@0.0.2 has been imported directly
 * in this case, we should ignore the version when looking for it in .bitmap
 * on the other hand, a dependency might be nested, and as a nested it's ok to have multiple
 * components with different versions, in this case, we look for the exact version.
 * so we do prefer an exact version, but if it doesn't find one try without a version.
 */


var getManipulateDirItemFromComponentVersion = function () {
  var _ref2 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(componentVersion, bitMap, repository, isDependency) {
    var id, componentMap, bitmapOrigin, origin, version, originallySharedDir, wrapDir;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            id = componentVersion.id;
            // when a component is now imported, ignore the version because if it was nested before, we just
            // replace it with the imported one.
            // however, the opposite is not true, if it is now nested and was imported before, we can have them both.
            // (see 'when imported component has lower dependencies versions than local' in import.e2e for such a case).
            // we might change this behavior as it is confusing.

            componentMap = isDependency ? bitMap.getComponentIfExist(id) : bitMap.getComponentPreferNonNested(id);
            bitmapOrigin = componentMap ? componentMap.origin : null;
            origin = getComponentOrigin(bitmapOrigin, isDependency);
            _context2.next = 6;
            return componentVersion.getVersion(repository);

          case 6:
            version = _context2.sent;
            originallySharedDir = getOriginallySharedDirIfNeeded(origin, version);
            wrapDir = getWrapDirIfNeeded(origin, version);
            return _context2.abrupt('return', { id, originallySharedDir, wrapDir });

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

  return function getManipulateDirItemFromComponentVersion(_x3, _x4, _x5, _x6) {
    return _ref2.apply(this, arguments);
  };
}();

/**
 * use this method while importing a component.
 * the data from bitMap is not enough because a component might be NESTED on bitmap but is now
 * imported.
 */


var getManipulateDirWhenImportingComponents = exports.getManipulateDirWhenImportingComponents = function () {
  var _ref3 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(bitMap, versionsDependencies, repository, shouldDependenciesSavedAsComponents) {
    var _this = this;

    var nonDependencies, manipulateDirDataP, manipulateDirData;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            nonDependencies = (_bitIds || _load_bitIds()).default.fromArray(versionsDependencies.map(function (versionDependency) {
              return versionDependency.component.id;
            }));
            manipulateDirDataP = versionsDependencies.map(function () {
              var _ref4 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(versionDependency) {
                var manipulateDirComponent, dependenciesSavedAsComponents, isDependency, manipulateDirDependenciesP, manipulateDirDependencies, manipulateDirDependenciesOnly;
                return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
                  while (1) {
                    switch (_context3.prev = _context3.next) {
                      case 0:
                        _context3.next = 2;
                        return getManipulateDirItemFromComponentVersion(versionDependency.component, bitMap, repository, false);

                      case 2:
                        manipulateDirComponent = _context3.sent;
                        dependenciesSavedAsComponents = shouldDependenciesSavedAsComponents.find(function (c) {
                          return c.id.isEqual(versionDependency.component.id);
                        });
                        // when dependencies are not save as components but as packages, they have the same behavior as
                        // imported components because each one of these dependencies is going to be isolated before
                        // npm installing it

                        isDependency = !dependenciesSavedAsComponents || dependenciesSavedAsComponents.saveDependenciesAsComponents;
                        manipulateDirDependenciesP = versionDependency.allDependencies.map(function (dependency) {
                          return getManipulateDirItemFromComponentVersion(dependency, bitMap, repository, isDependency);
                        });
                        _context3.next = 8;
                        return Promise.all(manipulateDirDependenciesP);

                      case 8:
                        manipulateDirDependencies = _context3.sent;

                        // a component might be a dependency and directly imported at the same time, in which case,
                        // it should be considered as imported, not nested
                        manipulateDirDependenciesOnly = manipulateDirDependencies.filter(function (m) {
                          return !nonDependencies.has(m.id);
                        });
                        return _context3.abrupt('return', [manipulateDirComponent].concat(_toConsumableArray(manipulateDirDependenciesOnly)));

                      case 11:
                      case 'end':
                        return _context3.stop();
                    }
                  }
                }, _callee3, _this);
              }));

              return function (_x11) {
                return _ref4.apply(this, arguments);
              };
            }());
            _context4.next = 4;
            return Promise.all(manipulateDirDataP);

          case 4:
            manipulateDirData = _context4.sent;
            return _context4.abrupt('return', (_ramda || _load_ramda()).default.flatten(manipulateDirData));

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

  return function getManipulateDirWhenImportingComponents(_x7, _x8, _x9, _x10) {
    return _ref3.apply(this, arguments);
  };
}();

exports.revertDirManipulationForPath = revertDirManipulationForPath;

var _path;

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

var _ramda;

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

var _bitId;

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

var _versionDependencies;

function _load_versionDependencies() {
  return _versionDependencies = _interopRequireDefault(require('../../scope/version-dependencies'));
}

var _utils;

function _load_utils() {
  return _utils = require('../../utils');
}

var _dependencies;

function _load_dependencies() {
  return _dependencies = require('../component/dependencies');
}

var _constants;

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

var _componentMap;

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

var _componentVersion;

function _load_componentVersion() {
  return _componentVersion = _interopRequireDefault(require('../../scope/component-version'));
}

var _bitIds;

function _load_bitIds() {
  return _bitIds = _interopRequireDefault(require('../../bit-id/bit-ids'));
}

var _repository;

function _load_repository() {
  return _repository = _interopRequireDefault(require('../../scope/objects/repository'));
}

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); } }

/**
 * find a shared directory among the files of the main component and its dependencies
 */
function calculateOriginallySharedDir(version) {
  var pathSep = '/'; // it works for Windows as well as all paths are normalized to Linux
  var filePaths = version.files.map(function (file) {
    return (0, (_utils || _load_utils()).pathNormalizeToLinux)(file.relativePath);
  });
  var allDependencies = new (_dependencies || _load_dependencies()).Dependencies(version.getAllDependencies());
  var dependenciesPaths = allDependencies.getSourcesPaths();
  var allPaths = [].concat(_toConsumableArray(filePaths), _toConsumableArray(dependenciesPaths));
  var sharedStart = (0, (_utils || _load_utils()).sharedStartOfArray)(allPaths);
  if (!sharedStart || !sharedStart.includes(pathSep)) return null;
  var sharedStartDirectories = sharedStart.split(pathSep);
  sharedStartDirectories.pop(); // the sharedStart ended with a slash, remove it.
  if (allPaths.some(function (p) {
    return p.replace(sharedStart, '') === (_constants || _load_constants()).PACKAGE_JSON;
  })) {
    // if package.json is located in an inside dir, don't consider that dir as a sharedDir, we
    // must keep this directory in order to not collide with the generated package.json.
    sharedStartDirectories.pop();
  }
  return sharedStartDirectories.join(pathSep);
}

function getOriginallySharedDirIfNeeded(origin, version) {
  if (origin !== (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED) return null;
  return calculateOriginallySharedDir(version);
}

/**
 * if one of the files is 'package.json' and it's on the root, we need a wrapper dir to avoid
 * collision with Bit generated package.json file.
 * also, if one of the files requires the root package.json, because we need to generate the
 * "package.json" file as a link once imported, we have to wrap it as well.
 */
function isWrapperDirNeeded(version) {
  var allDependencies = new (_dependencies || _load_dependencies()).Dependencies(version.getAllDependencies());
  var dependenciesSourcePaths = allDependencies.getSourcesPaths();
  return version.files.some(function (file) {
    return file.relativePath === (_constants || _load_constants()).PACKAGE_JSON;
  }) || dependenciesSourcePaths.some(function (dependencyPath) {
    return dependencyPath === (_constants || _load_constants()).PACKAGE_JSON;
  });
}

function getWrapDirIfNeeded(origin, version) {
  if (origin === (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED) return null;
  return isWrapperDirNeeded(version) ? (_constants || _load_constants()).WRAPPER_DIR : null;
}function getDependencyComponentMap(bitMap, dependencyId) {
  return bitMap.getComponentIfExist(dependencyId) || bitMap.getComponentIfExist(dependencyId, { ignoreVersion: true });
}

/**
 * an authored component that is now imported, is still authored.
 * however, nested component that is now imported directly, is actually imported.
 * if there is no entry for this component in bitmap, it is imported.
 */
function getComponentOrigin(bitmapOrigin, isDependency) {
  if (!bitmapOrigin) return isDependency ? (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED : (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED;
  if (bitmapOrigin === (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED && !isDependency) {
    return (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED;
  }
  return bitmapOrigin;
}

function revertDirManipulationForPath(pathStr, originallySharedDir, wrapDir) {
  var withSharedDir = addSharedDirForPath(pathStr, originallySharedDir);
  return removeWrapperDirFromPath(withSharedDir, wrapDir);
}

function addSharedDirForPath(pathStr, originallySharedDir) {
  var withSharedDir = originallySharedDir ? (_path || _load_path()).default.join(originallySharedDir, pathStr) : pathStr;
  return (0, (_utils || _load_utils()).pathNormalizeToLinux)(withSharedDir);
}

function removeWrapperDirFromPath(pathStr, wrapDir) {
  return wrapDir ? pathStr.replace(`${wrapDir}/`, '') : pathStr;
}