'use strict';

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

var _regenerator;

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

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var writeEnvFiles = exports.writeEnvFiles = function () {
  var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(_ref4) {
    var fullConfigDir = _ref4.fullConfigDir,
        env = _ref4.env,
        consumer = _ref4.consumer,
        component = _ref4.component,
        deleteOldFiles = _ref4.deleteOldFiles,
        _ref4$verbose = _ref4.verbose,
        verbose = _ref4$verbose === undefined ? false : _ref4$verbose;
    var ejectedDirectory, deps;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            if (env) {
              _context2.next = 2;
              break;
            }

            return _context2.abrupt('return', '');

          case 2:
            _context2.next = 4;
            return env.writeFilesToFs({ configDir: fullConfigDir, deleteOldFiles, verbose });

          case 4:
            ejectedDirectory = _context2.sent;
            deps = env instanceof (_compilerExtension || _load_compilerExtension()).default ? component.compilerDependencies : component.testerDependencies;
            _context2.next = 8;
            return (0, (_linkGenerator || _load_linkGenerator()).writeDependenciesLinksToDir)(fullConfigDir, component, deps, consumer);

          case 8:
            return _context2.abrupt('return', ejectedDirectory);

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

  return function writeEnvFiles(_x5) {
    return _ref5.apply(this, arguments);
  };
}();

var _path;

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

var _ramda;

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

var _consumerComponent;

function _load_consumerComponent() {
  return _consumerComponent = _interopRequireDefault(require('../component/consumer-component'));
}

var _bitJson;

function _load_bitJson() {
  return _bitJson = _interopRequireDefault(require('../bit-json'));
}

var _utils;

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

var _generalError;

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

var _bitMap;

function _load_bitMap() {
  return _bitMap = _interopRequireDefault(require('../bit-map'));
}

var _ejectNoDir;

function _load_ejectNoDir() {
  return _ejectNoDir = _interopRequireDefault(require('./exceptions/eject-no-dir'));
}

var _configDir;

function _load_configDir() {
  return _configDir = _interopRequireDefault(require('../bit-map/config-dir'));
}

var _linkGenerator;

function _load_linkGenerator() {
  return _linkGenerator = require('../../links/link-generator');
}

var _;

function _load_() {
  return _ = require('..');
}

var _compilerExtension;

function _load_compilerExtension() {
  return _compilerExtension = _interopRequireDefault(require('../../extensions/compiler-extension'));
}

var _testerExtension;

function _load_testerExtension() {
  return _testerExtension = _interopRequireDefault(require('../../extensions/tester-extension'));
}

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

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

exports.default = function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(component, consumer, configDir) {
    var override = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;

    var consumerPath, bitMap, oldConfigDir, componentMap, componentDir, configDirToValidate, deleteOldFiles, resolvedConfigDir, resolvedConfigDirFullPath, ejectedCompilerDirectoryP, ejectedTesterDirectoryP, _ref2, _ref3, ejectedCompilerDirectory, ejectedTesterDirectory, bitJsonDir, bitJsonDirFullPath, relativeEjectedCompilerDirectory, relativeEjectedTesterDirectory, oldBitJsonDir, oldBitJsonDirFullPath;

    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            consumerPath = consumer.getPath();
            bitMap = consumer.bitMap;
            oldConfigDir = (_ramda || _load_ramda()).default.path(['componentMap', 'configDir'], component);
            componentMap = component.componentMap;

            if (componentMap) {
              _context.next = 6;
              break;
            }

            throw new (_generalError || _load_generalError()).default('could not find component in the .bitmap file');

          case 6:
            componentDir = componentMap.getComponentDir();

            if (!(!componentDir && configDir.isUnderComponentDir)) {
              _context.next = 9;
              break;
            }

            throw new (_ejectNoDir || _load_ejectNoDir()).default(component.id.toStringWithoutVersion());

          case 9:
            // In case the user pass a path with the component dir replace it by the {COMPONENT_DIR} DSL
            // (To better support bit move for example)
            if (componentDir) {
              configDir.repalceByComponentDirDSL(componentDir);
            }
            if (!configDir.isUnderComponentDir) {
              configDirToValidate = _getDirToValidateAgainsetOtherComps(configDir);

              bitMap.validateConfigDir(component.id.toStringWithoutVersion(), configDirToValidate);
            }
            deleteOldFiles = !!componentMap.configDir && componentMap.configDir !== configDir.linuxDirPath;
            // Passing here the ENV_TYPE as well to make sure it's not removed since we need it later

            resolvedConfigDir = configDir.getResolved({ componentDir });
            resolvedConfigDirFullPath = (_path || _load_path()).default.normalize((_path || _load_path()).default.join(consumerPath, resolvedConfigDir.dirPath));
            ejectedCompilerDirectoryP = writeEnvFiles({
              fullConfigDir: resolvedConfigDirFullPath,
              env: component.compiler,
              consumer,
              component,
              deleteOldFiles,
              verbose: false
            });
            ejectedTesterDirectoryP = writeEnvFiles({
              fullConfigDir: resolvedConfigDirFullPath,
              env: component.tester,
              consumer,
              component,
              deleteOldFiles,
              verbose: false
            });
            _context.next = 18;
            return Promise.all([ejectedCompilerDirectoryP, ejectedTesterDirectoryP]);

          case 18:
            _ref2 = _context.sent;
            _ref3 = _slicedToArray(_ref2, 2);
            ejectedCompilerDirectory = _ref3[0];
            ejectedTesterDirectory = _ref3[1];
            bitJsonDir = resolvedConfigDir.getEnvTypeCleaned();
            bitJsonDirFullPath = (_path || _load_path()).default.normalize((_path || _load_path()).default.join(consumerPath, bitJsonDir.dirPath));
            relativeEjectedCompilerDirectory = _getRelativeDir(bitJsonDirFullPath, ejectedCompilerDirectory);
            relativeEjectedTesterDirectory = _getRelativeDir(bitJsonDirFullPath, ejectedTesterDirectory);
            _context.next = 28;
            return writeBitJson(component, bitJsonDirFullPath, relativeEjectedCompilerDirectory, relativeEjectedTesterDirectory, override);

          case 28:
            if (!deleteOldFiles) {
              _context.next = 37;
              break;
            }

            if (!oldConfigDir) {
              _context.next = 37;
              break;
            }

            oldBitJsonDir = oldConfigDir.getResolved({ componentDir }).getEnvTypeCleaned();
            oldBitJsonDirFullPath = (_path || _load_path()).default.join(consumerPath, oldBitJsonDir.dirPath);

            if (!(bitJsonDirFullPath !== oldBitJsonDirFullPath)) {
              _context.next = 37;
              break;
            }

            _context.next = 35;
            return (_bitJson || _load_bitJson()).default.removeIfExist(oldBitJsonDirFullPath);

          case 35:
            _context.next = 37;
            return (0, (_utils || _load_utils()).removeEmptyDir)(oldBitJsonDirFullPath);

          case 37:
            return _context.abrupt('return', {
              id: component.id.toStringWithoutVersion(),
              ejectedPath: configDir.linuxDirPath,
              ejectedFullPath: bitJsonDir.linuxDirPath
            });

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

  function ejectConf(_x2, _x3, _x4) {
    return _ref.apply(this, arguments);
  }

  return ejectConf;
}();

var writeBitJson = function () {
  var _ref6 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(component, bitJsonDir, ejectedCompilerDirectory, ejectedTesterDirectory) {
    var override = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
    var bitJson;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            bitJson = new (_bitJson || _load_bitJson()).default({
              version: component.version,
              scope: component.scope,
              lang: component.lang,
              bindingPrefix: component.bindingPrefix,
              compiler: component.compiler ? component.compiler.toBitJsonObject(ejectedCompilerDirectory) : {},
              tester: component.tester ? component.tester.toBitJsonObject(ejectedTesterDirectory) : {},
              dependencies: component.dependencies.asWritableObject(),
              devDependencies: component.devDependencies.asWritableObject(),
              packageDependencies: component.packageDependencies,
              devPackageDependencies: component.devPackageDependencies,
              peerPackageDependencies: component.peerPackageDependencies
            });
            return _context3.abrupt('return', bitJson.write({ bitDir: bitJsonDir, override }));

          case 2:
          case 'end':
            return _context3.stop();
        }
      }
    }, _callee3, undefined);
  }));

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

var _getRelativeDir = function _getRelativeDir(bitJsonDir, envDir) {
  var res = envDir;
  var sharedStart = (0, (_utils || _load_utils()).sharedStartOfArray)([bitJsonDir, envDir]);
  if (sharedStart) {
    res = (_path || _load_path()).default.relative(sharedStart, envDir);
  }

  return res;
};

/**
 * get the config dir which needed to be searched in other components to validate there is no conflicts
 * That's means check that the dir is not inside the comp dir
 * and get the dir without the dynamic parts
 * @param {*} configDir
 */
var _getDirToValidateAgainsetOtherComps = function _getDirToValidateAgainsetOtherComps(configDir) {
  // In case it's inside the component dir it can't conflicts with other comps
  if (configDir.isUnderComponentDir) {
    return null;
  }
  return configDir.getCleaned({ cleanComponentDir: false, cleanEnvType: true }).linuxDirPath;
};