'use strict';

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

var _regenerator;

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

var _bluebird;

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

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 getEjectConfDataToPersist = exports.getEjectConfDataToPersist = function () {
  var _ref3 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(component, consumer, bitMap, configDir) {
    var oldConfigDir, componentMap, componentDir, configDirToValidate, deleteOldFiles, resolvedConfigDir, ejectedCompilerDirectoryP, ejectedTesterDirectoryP, _ref4, _ref5, ejectedCompilerDirectory, ejectedTesterDirectory, dataToPersist, id, bitJsonDir, consumerPath, bitJsonDirFullPath, relativeEjectedCompilerDirectory, relativeEjectedTesterDirectory, removedFromOverrides, bitJson, jsonFilesToWrite, consumerConfigFiles, oldBitJsonDir, oldBitJsonDirFullPath, bitJsonToRemove;

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

            if (componentMap) {
              _context2.next = 4;
              break;
            }

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

          case 4:
            componentDir = componentMap.getComponentDir();

            if (!(!componentDir && configDir.isUnderComponentDir)) {
              _context2.next = 7;
              break;
            }

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

          case 7:
            // 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.replaceByComponentDirDSL(componentDir);
            }
            if (!configDir.isUnderComponentDir) {
              configDirToValidate = _getDirToValidateAgainstOtherComps(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 });
            ejectedCompilerDirectoryP = populateEnvFilesToWrite({
              configDir: resolvedConfigDir.dirPath,
              env: component.compiler,
              consumer,
              bitMap,
              component,
              deleteOldFiles,
              verbose: false
            });
            ejectedTesterDirectoryP = populateEnvFilesToWrite({
              configDir: resolvedConfigDir.dirPath,
              env: component.tester,
              consumer,
              bitMap,
              component,
              deleteOldFiles,
              verbose: false
            });
            _context2.next = 15;
            return Promise.all([ejectedCompilerDirectoryP, ejectedTesterDirectoryP]);

          case 15:
            _ref4 = _context2.sent;
            _ref5 = _slicedToArray(_ref4, 2);
            ejectedCompilerDirectory = _ref5[0];
            ejectedTesterDirectory = _ref5[1];
            dataToPersist = new (_dataToPersist || _load_dataToPersist()).default();

            if (component.compiler) dataToPersist.merge(component.compiler.dataToPersist);
            if (component.tester) dataToPersist.merge(component.tester.dataToPersist);

            id = component.id.toStringWithoutVersion();

            if (consumer) {
              _context2.next = 25;
              break;
            }

            return _context2.abrupt('return', {
              id,
              ejectedPath: configDir.linuxDirPath,
              dataToPersist
            });

          case 25:
            bitJsonDir = resolvedConfigDir.getEnvTypeCleaned();
            consumerPath = consumer.getPath();
            bitJsonDirFullPath = (_path || _load_path()).default.normalize((_path || _load_path()).default.join(consumerPath, bitJsonDir.dirPath));
            relativeEjectedCompilerDirectory = _getRelativeDir(bitJsonDirFullPath, consumer.toAbsolutePath(ejectedCompilerDirectory));
            relativeEjectedTesterDirectory = _getRelativeDir(bitJsonDirFullPath, consumer.toAbsolutePath(ejectedTesterDirectory));
            removedFromOverrides = consumer.config.overrides.removeExactMatch(component.id);

            if (component.compiler) dataToPersist.merge(component.compiler.dataToPersist);
            if (component.tester) dataToPersist.merge(component.tester.dataToPersist);
            bitJson = getBitJsonToWrite(component, relativeEjectedCompilerDirectory, relativeEjectedTesterDirectory);
            _context2.next = 36;
            return bitJson.prepareToWrite({ bitDir: bitJsonDir.dirPath });

          case 36:
            jsonFilesToWrite = _context2.sent;

            dataToPersist.addManyFiles(jsonFilesToWrite);

            if (!removedFromOverrides) {
              _context2.next = 43;
              break;
            }

            _context2.next = 41;
            return consumer.config.prepareToWrite({ bitDir: '.' });

          case 41:
            consumerConfigFiles = _context2.sent;

            dataToPersist.addManyFiles(consumerConfigFiles);

          case 43:

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

                if (bitJsonDirFullPath !== oldBitJsonDirFullPath) {
                  bitJsonToRemove = (_abstractConfig || _load_abstractConfig()).default.composeBitJsonPath(oldBitJsonDir.dirPath);

                  dataToPersist.removePath(new (_removePath || _load_removePath()).default(bitJsonToRemove, true));
                }
              }
            }
            return _context2.abrupt('return', {
              id,
              ejectedPath: configDir.linuxDirPath,
              ejectedFullPath: bitJsonDir.linuxDirPath,
              dataToPersist
            });

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

  return function getEjectConfDataToPersist(_x4, _x5, _x6, _x7) {
    return _ref3.apply(this, arguments);
  };
}();

var writeEnvFiles = exports.writeEnvFiles = function () {
  var _ref6 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(_ref7) {
    var configDir = _ref7.configDir,
        env = _ref7.env,
        consumer = _ref7.consumer,
        component = _ref7.component,
        deleteOldFiles = _ref7.deleteOldFiles,
        _ref7$verbose = _ref7.verbose,
        verbose = _ref7$verbose === undefined ? false : _ref7$verbose;
    var ejectedDirectory;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            if (env) {
              _context3.next = 2;
              break;
            }

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

          case 2:
            _context3.next = 4;
            return populateEnvFilesToWrite({
              configDir,
              env,
              consumer,
              // $FlowFixMe todo: fix!
              bitMap: consumer.bitMap,
              component,
              deleteOldFiles,
              verbose
            });

          case 4:
            ejectedDirectory = _context3.sent;

            if (!env.dataToPersist) {
              _context3.next = 9;
              break;
            }

            if (consumer) env.dataToPersist.addBasePath(consumer.getPath());
            _context3.next = 9;
            return env.dataToPersist.persistAllToFS();

          case 9:
            return _context3.abrupt('return', ejectedDirectory);

          case 10:
          case 'end':
            return _context3.stop();
        }
      }
    }, _callee3, this);
  }));

  return function writeEnvFiles(_x8) {
    return _ref6.apply(this, arguments);
  };
}();

/**
 * populates the env files into env.dataToPersist
 */


var populateEnvFilesToWrite = exports.populateEnvFilesToWrite = function () {
  var _ref8 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(_ref9) {
    var configDir = _ref9.configDir,
        env = _ref9.env,
        consumer = _ref9.consumer,
        bitMap = _ref9.bitMap,
        component = _ref9.component,
        deleteOldFiles = _ref9.deleteOldFiles,
        _ref9$verbose = _ref9.verbose,
        verbose = _ref9$verbose === undefined ? false : _ref9$verbose;
    var envType, ejectedDirectory, deps, links;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            if (env) {
              _context4.next = 2;
              break;
            }

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

          case 2:
            envType = env instanceof (_compilerExtension || _load_compilerExtension()).default ? (_constants || _load_constants()).COMPILER_ENV_TYPE : (_constants || _load_constants()).TESTER_ENV_TYPE;
            ejectedDirectory = env.populateDataToPersist({ configDir, deleteOldFiles, consumer, envType, verbose });
            deps = env instanceof (_compilerExtension || _load_compilerExtension()).default ? component.compilerDependencies : component.testerDependencies;
            // $FlowFixMe will be fixed with the Capsule feature

            _context4.next = 7;
            return (0, (_linkGenerator || _load_linkGenerator()).getLinksByDependencies)(configDir, component, deps, consumer, bitMap);

          case 7:
            links = _context4.sent;

            env.dataToPersist.addManyFiles(links);
            return _context4.abrupt('return', ejectedDirectory);

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

  return function populateEnvFilesToWrite(_x9) {
    return _ref8.apply(this, arguments);
  };
}();

var _path;

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

var _ramda;

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

var _config;

function _load_config() {
  return _config = _interopRequireDefault(require('../config'));
}

var _utils;

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

var _generalError;

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

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

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

var _testerExtension;

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

var _dataToPersist;

function _load_dataToPersist() {
  return _dataToPersist = _interopRequireDefault(require('../component/sources/data-to-persist'));
}

var _constants;

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

var _removePath;

function _load_removePath() {
  return _removePath = _interopRequireDefault(require('../component/sources/remove-path'));
}

var _abstractConfig;

function _load_abstractConfig() {
  return _abstractConfig = _interopRequireDefault(require('../config/abstract-config'));
}

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

exports.default = function () {
  var _ref = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(component, consumer, configDir) {
    var _ref2, id, ejectedPath, ejectedFullPath, dataToPersist;

    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return getEjectConfDataToPersist(component, consumer, consumer.bitMap, configDir);

          case 2:
            _ref2 = _context.sent;
            id = _ref2.id;
            ejectedPath = _ref2.ejectedPath;
            ejectedFullPath = _ref2.ejectedFullPath;
            dataToPersist = _ref2.dataToPersist;

            dataToPersist.addBasePath(consumer.getPath());
            _context.next = 10;
            return dataToPersist.persistAllToFS();

          case 10:
            return _context.abrupt('return', {
              id,
              ejectedPath,
              ejectedFullPath
            });

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

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

  return ejectConf;
}();

var getBitJsonToWrite = function getBitJsonToWrite(component, ejectedCompilerDirectory, ejectedTesterDirectory) {
  var componentConfig = (_config || _load_config()).default.fromComponent(component);
  componentConfig.compiler = component.compiler ? component.compiler.toBitJsonObject(ejectedCompilerDirectory) : {};
  componentConfig.tester = component.tester ? component.tester.toBitJsonObject(ejectedTesterDirectory) : {};
  return componentConfig;
};

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 _getDirToValidateAgainstOtherComps = function _getDirToValidateAgainstOtherComps(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;
};