'use strict';

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

var _regenerator;

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

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _uuid;

function _load_uuid() {
  return _uuid = _interopRequireDefault(require('uuid'));
}

var _fsExtra;

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

var _path;

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

var _ramda;

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

var _scope;

function _load_scope() {
  return _scope = require('../scope');
}

var _bitId;

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

var _constants;

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

var _utils;

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

var _logger;

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

var _consumer;

function _load_consumer() {
  return _consumer = require('../consumer');
}

var _writeComponents;

function _load_writeComponents() {
  return _writeComponents = _interopRequireDefault(require('../consumer/component-ops/write-components'));
}

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

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var ENV_IS_INSTALLED_FILENAME = '.bit_env_has_installed';

var Environment = function () {
  function Environment(scope, dir) {
    _classCallCheck(this, Environment);

    this.scope = scope;
    this.path = dir || (_path || _load_path()).default.join(scope.getPath(), (_constants || _load_constants()).ISOLATED_ENV_ROOT, (0, (_uuid || _load_uuid()).default)());
    (_logger || _load_logger()).default.debug(`creating a new isolated environment at ${this.path}`);
  }

  _createClass(Environment, [{
    key: 'create',
    value: function () {
      var _ref = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee() {
        return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _context.next = 2;
                return (0, (_utils || _load_utils()).mkdirp)(this.path);

              case 2:
                _context.next = 4;
                return (_consumer || _load_consumer()).Consumer.createWithExistingScope(this.path, this.scope, true);

              case 4:
                this.consumer = _context.sent;

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

      function create() {
        return _ref.apply(this, arguments);
      }

      return create;
    }()

    /**
     * import a component end to end. Including importing the dependencies and installing the npm
     * packages.
     *
     * @param {string | BitId} rawId - the component id to isolate
     * @param {IsolateOptions} opts
     * @return {Promise.<Component>}
     */

  }, {
    key: 'isolateComponent',
    value: function () {
      var _ref2 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(rawId, opts) {
        var bitId, componentsWithDependencies, writeToPath, concreteOpts;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                bitId = typeof rawId === 'string' ? (_bitId || _load_bitId()).BitId.parse(rawId) : rawId;
                _context2.next = 3;
                return this.scope.getMany([bitId]);

              case 3:
                componentsWithDependencies = _context2.sent;
                writeToPath = opts.writeToPath || this.path;
                concreteOpts = {
                  consumer: this.consumer,
                  componentsWithDependencies,
                  writeToPath,
                  override: opts.override,
                  writePackageJson: !opts.noPackageJson,
                  writeBitJson: opts.conf,
                  writeBitDependencies: opts.writeBitDependencies,
                  createNpmLinkFiles: opts.createNpmLinkFiles,
                  saveDependenciesAsComponents: opts.saveDependenciesAsComponents !== false,
                  writeDists: opts.dist,
                  installNpmPackages: !!opts.installPackages, // convert to boolean
                  installPeerDependencies: !!opts.installPackages, // convert to boolean
                  addToRootPackageJson: false,
                  verbose: opts.verbose,
                  excludeRegistryPrefix: !!opts.excludeRegistryPrefix,
                  silentPackageManagerResult: opts.silentPackageManagerResult
                };
                _context2.next = 8;
                return (0, (_writeComponents || _load_writeComponents()).default)(concreteOpts);

              case 8:
                _context2.next = 10;
                return Environment.markEnvironmentAsInstalled(writeToPath);

              case 10:
                return _context2.abrupt('return', (_ramda || _load_ramda()).default.head(componentsWithDependencies));

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

      function isolateComponent(_x, _x2) {
        return _ref2.apply(this, arguments);
      }

      return isolateComponent;
    }()

    /**
     * It helps to make sure an environment is installed. Otherwise, in case a user interrupts the environment
     * installation process, it won't be installed again.
     */

  }, {
    key: 'getPath',
    value: function getPath() {
      return this.path;
    }
  }, {
    key: 'destroy',
    value: function destroy() {
      (_logger || _load_logger()).default.debug(`destroying the isolated environment at ${this.path}`);
      return (_fsExtra || _load_fsExtra()).default.remove(this.path);
    }
  }, {
    key: 'destroyIfExist',
    value: function () {
      var _ref3 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3() {
        var isExist;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                _context3.next = 2;
                return (_fsExtra || _load_fsExtra()).default.exists(this.path);

              case 2:
                isExist = _context3.sent;

                if (!isExist) {
                  _context3.next = 6;
                  break;
                }

                (_logger || _load_logger()).default.debug(`destroying existing environment in path ${this.path}`);
                return _context3.abrupt('return', this.destroy());

              case 6:
                return _context3.abrupt('return', false);

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

      function destroyIfExist() {
        return _ref3.apply(this, arguments);
      }

      return destroyIfExist;
    }()
  }], [{
    key: 'markEnvironmentAsInstalled',
    value: function markEnvironmentAsInstalled(dir) {
      var filePath = (_path || _load_path()).default.join(dir, ENV_IS_INSTALLED_FILENAME);
      return (0, (_utils || _load_utils()).outputFile)({ filePath, content: '' });
    }
  }, {
    key: 'isEnvironmentInstalled',
    value: function isEnvironmentInstalled(dir) {
      var filePath = (_path || _load_path()).default.join(dir, ENV_IS_INSTALLED_FILENAME);
      return (_fsExtra || _load_fsExtra()).default.existsSync(filePath);
    }
  }]);

  return Environment;
}();

exports.default = Environment;