'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.removeComponentsFromWorkspacesAndDependencies = exports.addWorkspacesToPackageJson = exports.updateAttribute = exports.write = exports.changeDependenciesToRelativeSyntax = exports.addComponentsWithVersionToRoot = exports.addComponentsToRoot = undefined;

var _regenerator;

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

var _bluebird;

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

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

/**
 * Add components as dependencies to root package.json
 */
var addComponentsToRoot = exports.addComponentsToRoot = function () {
  var _ref = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(consumer, components) {
    var componentsToAdd;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            componentsToAdd = components.reduce(function (acc, component) {
              var componentMap = consumer.bitMap.getComponent(component.id);
              if (componentMap.origin !== (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED) return acc;
              if (!componentMap.rootDir) {
                throw new (_generalError || _load_generalError()).default(`rootDir is missing from an imported component ${component.id.toString()}`);
              }
              var locationAsUnixFormat = convertToValidPathForPackageManager(componentMap.rootDir);
              var packageName = (0, (_componentIdToPackageName || _load_componentIdToPackageName()).default)(component.id, component.bindingPrefix);
              acc[packageName] = locationAsUnixFormat;
              return acc;
            }, {});

            if (!(_ramda || _load_ramda()).default.isEmpty(componentsToAdd)) {
              _context.next = 3;
              break;
            }

            return _context.abrupt('return');

          case 3:
            _context.next = 5;
            return _addDependenciesPackagesIntoPackageJson(consumer.getPath(), componentsToAdd);

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

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

/**
 * Add given components with their versions to root package.json
 */


var addComponentsWithVersionToRoot = exports.addComponentsWithVersionToRoot = function () {
  var _ref2 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(consumer, componentsVersions) {
    var componentsToAdd;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            componentsToAdd = (_ramda || _load_ramda()).default.fromPairs(componentsVersions.map(function (_ref3) {
              var component = _ref3.component,
                  version = _ref3.version;

              var packageName = (0, (_componentIdToPackageName || _load_componentIdToPackageName()).default)(component.toBitId(), component.bindingPrefix);
              return [packageName, version];
            }));
            _context2.next = 3;
            return _addDependenciesPackagesIntoPackageJson(consumer.getPath(), componentsToAdd);

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

  return function addComponentsWithVersionToRoot(_x3, _x4) {
    return _ref2.apply(this, arguments);
  };
}();

var changeDependenciesToRelativeSyntax = exports.changeDependenciesToRelativeSyntax = function () {
  var _ref4 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(consumer, components, dependencies) {
    var _this = this;

    var dependenciesIds, updateComponentPackageJson, packageJsonFiles, getPackages;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            getPackages = function getPackages(deps, componentMap) {
              return deps.get().reduce(function (acc, dependency) {
                var dependencyId = dependency.id.toStringWithoutVersion();
                if (dependenciesIds.searchWithoutVersion(dependency.id)) {
                  var dependencyComponent = dependencies.find(function (d) {
                    return d.id.isEqualWithoutVersion(dependency.id);
                  });
                  if (!dependencyComponent) {
                    throw new Error('getDependenciesAsPackages, dependencyComponent is missing');
                  }
                  var dependencyComponentMap = consumer.bitMap.getComponentIfExist(dependencyComponent.id);
                  var dependencyPackageValue = getPackageDependencyValue(dependencyId, componentMap, dependencyComponentMap);
                  if (dependencyPackageValue) {
                    var packageName = (0, (_componentIdToPackageName || _load_componentIdToPackageName()).default)(dependency.id, dependencyComponent.bindingPrefix || (0, (_npmRegistryName || _load_npmRegistryName()).default)());
                    acc[packageName] = dependencyPackageValue;
                  }
                }
                return acc;
              }, {});
            };

            dependenciesIds = (_bitId || _load_bitId()).BitIds.fromArray(dependencies.map(function (dependency) {
              return dependency.id;
            }));

            updateComponentPackageJson = function () {
              var _ref5 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(component) {
                var componentMap, componentRootDir, packageJsonFile, devDeps, compilerDeps, testerDeps;
                return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
                  while (1) {
                    switch (_context3.prev = _context3.next) {
                      case 0:
                        componentMap = consumer.bitMap.getComponent(component.id);
                        componentRootDir = componentMap.rootDir;

                        if (componentRootDir) {
                          _context3.next = 4;
                          break;
                        }

                        return _context3.abrupt('return', null);

                      case 4:
                        _context3.next = 6;
                        return (_packageJsonFile || _load_packageJsonFile()).default.load(componentRootDir);

                      case 6:
                        packageJsonFile = _context3.sent;

                        if (packageJsonFile.fileExist) {
                          _context3.next = 9;
                          break;
                        }

                        return _context3.abrupt('return', null);

                      case 9:
                        // if package.json doesn't exist no need to update anything
                        devDeps = getPackages(component.devDependencies, componentMap);
                        compilerDeps = getPackages(component.compilerDependencies, componentMap);
                        testerDeps = getPackages(component.testerDependencies, componentMap);

                        packageJsonFile.addDependencies(getPackages(component.dependencies, componentMap));
                        packageJsonFile.addDevDependencies(_extends({}, devDeps, compilerDeps, testerDeps));
                        return _context3.abrupt('return', packageJsonFile.toJSONFile());

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

              return function updateComponentPackageJson(_x8) {
                return _ref5.apply(this, arguments);
              };
            }();

            _context4.next = 5;
            return Promise.all(components.map(function (component) {
              return updateComponentPackageJson(component);
            }));

          case 5:
            packageJsonFiles = _context4.sent;
            return _context4.abrupt('return', packageJsonFiles.filter(function (file) {
              return file;
            }));

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

  return function changeDependenciesToRelativeSyntax(_x5, _x6, _x7) {
    return _ref4.apply(this, arguments);
  };
}();

var write = exports.write = function () {
  var _ref6 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5(consumer, component, bitDir) {
    var writeBitDependencies = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
    var excludeRegistryPrefix = arguments[4];

    var _preparePackageJsonTo, packageJson, distPackageJson;

    return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
      while (1) {
        switch (_context5.prev = _context5.next) {
          case 0:
            _preparePackageJsonTo = preparePackageJsonToWrite(consumer, component, bitDir, writeBitDependencies, excludeRegistryPrefix), packageJson = _preparePackageJsonTo.packageJson, distPackageJson = _preparePackageJsonTo.distPackageJson;
            _context5.next = 3;
            return packageJson.write();

          case 3:
            if (!distPackageJson) {
              _context5.next = 6;
              break;
            }

            _context5.next = 6;
            return distPackageJson.write();

          case 6:
            return _context5.abrupt('return', packageJson);

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

  return function write(_x9, _x10, _x11) {
    return _ref6.apply(this, arguments);
  };
}();

var updateAttribute = exports.updateAttribute = function () {
  var _ref7 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee6(consumer, componentDir, attributeName, attributeValue) {
    var packageJsonFile;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee6$(_context6) {
      while (1) {
        switch (_context6.prev = _context6.next) {
          case 0:
            _context6.next = 2;
            return (_packageJsonFile || _load_packageJsonFile()).default.load(componentDir);

          case 2:
            packageJsonFile = _context6.sent;

            if (packageJsonFile.fileExist) {
              _context6.next = 5;
              break;
            }

            return _context6.abrupt('return');

          case 5:
            // package.json doesn't exist, that's fine, no need to update anything
            packageJsonFile.addOrUpdateProperty(attributeName, attributeValue);
            _context6.next = 8;
            return packageJsonFile.write();

          case 8:
          case 'end':
            return _context6.stop();
        }
      }
    }, _callee6, this);
  }));

  return function updateAttribute(_x15, _x16, _x17, _x18) {
    return _ref7.apply(this, arguments);
  };
}();

/**
 * Adds workspace array to package.json - only if user wants to work with yarn workspaces
 */


var addWorkspacesToPackageJson = exports.addWorkspacesToPackageJson = function () {
  var _ref8 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee7(consumer, customImportPath) {
    var rootDir, dependenciesDirectory, componentsDefaultDirectory, driver, PackageJson;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee7$(_context7) {
      while (1) {
        switch (_context7.prev = _context7.next) {
          case 0:
            if (!(consumer.config.manageWorkspaces && consumer.config.packageManager === 'yarn' && consumer.config.useWorkspaces)) {
              _context7.next = 8;
              break;
            }

            rootDir = consumer.getPath();
            dependenciesDirectory = consumer.config.dependenciesDirectory;
            componentsDefaultDirectory = consumer.dirStructure.componentsDefaultDirectory;
            driver = consumer.driver.getDriver(false);
            PackageJson = driver.PackageJson;
            _context7.next = 8;
            return PackageJson.addWorkspacesToPackageJson(rootDir, componentsDefaultDirectory + (_constants || _load_constants()).SUB_DIRECTORIES_GLOB_PATTERN, dependenciesDirectory + (_constants || _load_constants()).SUB_DIRECTORIES_GLOB_PATTERN, customImportPath ? consumer.getPathRelativeToConsumer(customImportPath) : customImportPath);

          case 8:
          case 'end':
            return _context7.stop();
        }
      }
    }, _callee7, this);
  }));

  return function addWorkspacesToPackageJson(_x19, _x20) {
    return _ref8.apply(this, arguments);
  };
}();

var removeComponentsFromWorkspacesAndDependencies = exports.removeComponentsFromWorkspacesAndDependencies = function () {
  var _ref9 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee8(consumer, componentIds) {
    var rootDir, driver, PackageJson, dirsToRemove;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee8$(_context8) {
      while (1) {
        switch (_context8.prev = _context8.next) {
          case 0:
            rootDir = consumer.getPath();
            driver = consumer.driver.getDriver(false);
            PackageJson = driver.PackageJson;

            if (!(consumer.config.manageWorkspaces && consumer.config.packageManager === 'yarn' && consumer.config.useWorkspaces)) {
              _context8.next = 7;
              break;
            }

            dirsToRemove = componentIds.map(function (id) {
              return consumer.bitMap.getComponent(id, { ignoreVersion: true }).rootDir;
            });
            _context8.next = 7;
            return PackageJson.removeComponentsFromWorkspaces(rootDir, dirsToRemove);

          case 7:
            _context8.next = 9;
            return PackageJson.removeComponentsFromDependencies(rootDir, (0, (_npmRegistryName || _load_npmRegistryName()).default)(), componentIds.map(function (id) {
              return id.toStringWithoutVersion();
            }));

          case 9:
            _context8.next = 11;
            return removeComponentsFromNodeModules(consumer, componentIds);

          case 11:
          case 'end':
            return _context8.stop();
        }
      }
    }, _callee8, this);
  }));

  return function removeComponentsFromWorkspacesAndDependencies(_x21, _x22) {
    return _ref9.apply(this, arguments);
  };
}();

var _addDependenciesPackagesIntoPackageJson = function () {
  var _ref10 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee9(dir, dependencies) {
    var packageJsonFile;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee9$(_context9) {
      while (1) {
        switch (_context9.prev = _context9.next) {
          case 0:
            _context9.next = 2;
            return (_packageJsonFile || _load_packageJsonFile()).default.load(dir);

          case 2:
            packageJsonFile = _context9.sent;

            packageJsonFile.addDependencies(dependencies);
            _context9.next = 6;
            return packageJsonFile.write();

          case 6:
          case 'end':
            return _context9.stop();
        }
      }
    }, _callee9, this);
  }));

  return function _addDependenciesPackagesIntoPackageJson(_x23, _x24) {
    return _ref10.apply(this, arguments);
  };
}();

var removeComponentsFromNodeModules = function () {
  var _ref11 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee10(consumer, componentIds) {
    var registryPrefix, pathsToRemove;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee10$(_context10) {
      while (1) {
        switch (_context10.prev = _context10.next) {
          case 0:
            (_logger || _load_logger()).default.debug(`removeComponentsFromNodeModules: ${componentIds.map(function (c) {
              return c.toString();
            }).join(', ')}`);
            registryPrefix = (0, (_npmRegistryName || _load_npmRegistryName()).default)();
            // paths without scope name, don't have a symlink in node-modules

            pathsToRemove = componentIds.map(function (id) {
              return id.scope ? (0, (_componentNodeModulesPath || _load_componentNodeModulesPath()).default)(registryPrefix, id) : null;
            }).filter(function (a) {
              return a;
            }); // remove null

            (_logger || _load_logger()).default.debug(`deleting the following paths: ${pathsToRemove.join('\n')}`);
            // $FlowFixMe nulls were removed in the previous filter function
            return _context10.abrupt('return', Promise.all(pathsToRemove.map(function (componentPath) {
              return (_fsExtra || _load_fsExtra()).default.remove(consumer.toAbsolutePath(componentPath));
            })));

          case 5:
          case 'end':
            return _context10.stop();
        }
      }
    }, _callee10, this);
  }));

  return function removeComponentsFromNodeModules(_x25, _x26) {
    return _ref11.apply(this, arguments);
  };
}();

exports.preparePackageJsonToWrite = preparePackageJsonToWrite;

var _ramda;

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

var _fsExtra;

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

var _bitId;

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

var _constants;

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

var _componentMap;

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

var _utils;

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

var _path;

function _load_path() {
  return _path = require('../../utils/path');
}

var _componentNodeModulesPath;

function _load_componentNodeModulesPath() {
  return _componentNodeModulesPath = _interopRequireDefault(require('../../utils/bit/component-node-modules-path'));
}

var _logger;

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

var _generalError;

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

var _jsonFile;

function _load_jsonFile() {
  return _jsonFile = _interopRequireDefault(require('./sources/json-file'));
}

var _npmRegistryName;

function _load_npmRegistryName() {
  return _npmRegistryName = _interopRequireDefault(require('../../utils/bit/npm-registry-name'));
}

var _componentIdToPackageName;

function _load_componentIdToPackageName() {
  return _componentIdToPackageName = _interopRequireDefault(require('../../utils/bit/component-id-to-package-name'));
}

var _packageJsonFile;

function _load_packageJsonFile() {
  return _packageJsonFile = _interopRequireDefault(require('./package-json-file'));
}

var _searchFilesIgnoreExt;

function _load_searchFilesIgnoreExt() {
  return _searchFilesIgnoreExt = _interopRequireDefault(require('../../utils/fs/search-files-ignore-ext'));
}

var _componentVersion;

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

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

function preparePackageJsonToWrite(consumer, component, bitDir) {
  var override = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
  var writeBitDependencies = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
  var excludeRegistryPrefix = arguments[5];

  (_logger || _load_logger()).default.debug(`package-json.preparePackageJsonToWrite. bitDir ${bitDir}. override ${override.toString()}`);
  var getBitDependencies = function getBitDependencies(dependencies) {
    if (!writeBitDependencies) return {};
    return dependencies.get().reduce(function (acc, dep) {
      var packageDependency = consumer ? getPackageDependency(consumer, dep.id, component.id) : null;
      var packageName = (0, (_componentIdToPackageName || _load_componentIdToPackageName()).default)(dep.id, component.bindingPrefix || (0, (_npmRegistryName || _load_npmRegistryName()).default)());
      acc[packageName] = packageDependency;
      return acc;
    }, {});
  };
  var addDependencies = function addDependencies(packageJsonFile) {
    packageJsonFile.addDependencies(bitDependencies);
    packageJsonFile.addDevDependencies(_extends({}, bitDevDependencies, bitCompilerDependencies, bitTesterDependencies));
  };
  var bitDependencies = getBitDependencies(component.dependencies);
  var bitDevDependencies = getBitDependencies(component.devDependencies);
  var bitCompilerDependencies = getBitDependencies(component.compilerDependencies);
  var bitTesterDependencies = getBitDependencies(component.testerDependencies);
  var packageJson = (_packageJsonFile || _load_packageJsonFile()).default.createFromComponent(bitDir, component, excludeRegistryPrefix);
  var main = (0, (_path || _load_path()).pathNormalizeToLinux)(component.dists.calculateMainDistFile(component.mainFile));
  packageJson.addOrUpdateProperty('main', main);
  addDependencies(packageJson);
  var distPackageJson = void 0;
  if (!component.dists.isEmpty() && !component.dists.areDistsInsideComponentDir) {
    var distRootDir = component.dists.distsRootDir;
    if (!distRootDir) throw new (_generalError || _load_generalError()).default('component.dists.distsRootDir is not defined yet');
    distPackageJson = (_packageJsonFile || _load_packageJsonFile()).default.createFromComponent(distRootDir, component, excludeRegistryPrefix);
    var distMainFile = (0, (_searchFilesIgnoreExt || _load_searchFilesIgnoreExt()).default)(component.dists.get(), component.mainFile, 'relative');
    distPackageJson.addOrUpdateProperty('main', component.dists.getMainDistFile() || distMainFile);
    addDependencies(distPackageJson);
  }

  return { packageJson, distPackageJson };
}

function convertToValidPathForPackageManager(pathStr) {
  var prefix = 'file:'; // it works for both, Yarn and NPM
  return prefix + (pathStr.startsWith('.') ? pathStr : `./${pathStr}`);
}

/**
 * Only imported components should be saved with relative path in package.json
 * If a component is nested or imported as a package dependency, it should be saved with the version
 * If a component is authored, no need to save it as a dependency of the imported component because
 * the root package.json takes care of it already.
 */
function getPackageDependencyValue(dependencyId, parentComponentMap, dependencyComponentMap) {
  if (!dependencyComponentMap || dependencyComponentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.NESTED) {
    return dependencyId.version;
  }
  if (dependencyComponentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.AUTHORED) {
    return null;
  }
  var dependencyRootDir = dependencyComponentMap.rootDir;
  if (!dependencyRootDir) {
    throw new (_generalError || _load_generalError()).default(`rootDir is missing from an imported component ${dependencyId.toString()}`);
  }
  if (!parentComponentMap.rootDir) throw new (_generalError || _load_generalError()).default('rootDir is missing from an imported component');
  var rootDirRelative = (0, (_utils || _load_utils()).pathRelativeLinux)(parentComponentMap.rootDir, dependencyRootDir);
  return convertToValidPathForPackageManager(rootDirRelative);
}

function getPackageDependency(consumer, dependencyId, parentId) {
  var parentComponentMap = consumer.bitMap.getComponent(parentId);
  var dependencyComponentMap = consumer.bitMap.getComponentIfExist(dependencyId);
  return getPackageDependencyValue(dependencyId, parentComponentMap, dependencyComponentMap);
}