'use strict';

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

var _regenerator;

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

var _buildIfNeeded = function () {
  var _ref4 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(_ref3) {
    var component = _ref3.component,
        consumer = _ref3.consumer,
        componentMap = _ref3.componentMap,
        scope = _ref3.scope,
        verbose = _ref3.verbose,
        directory = _ref3.directory,
        keep = _ref3.keep;
    var compiler, isolatedEnvironment, isolateOpts, componentWithDependencies, isolatedComponent, result;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            compiler = component.compiler;

            if (compiler) {
              _context2.next = 3;
              break;
            }

            throw new (_generalError || _load_generalError()).default('compiler was not found, nothing to build');

          case 3:
            if (!(!compiler.action && !compiler.oldAction)) {
              _context2.next = 5;
              break;
            }

            throw new (_invalidCompilerInterface || _load_invalidCompilerInterface()).default(compiler.name);

          case 5:
            if (!consumer) {
              _context2.next = 7;
              break;
            }

            return _context2.abrupt('return', _runBuild({ component, componentRoot: consumer.getPath(), consumer, componentMap, verbose }));

          case 7:
            if (!component.isolatedEnvironment) {
              _context2.next = 9;
              break;
            }

            return _context2.abrupt('return', _runBuild({ component, componentRoot: component.writtenPath, consumer, componentMap, verbose }));

          case 9:
            isolatedEnvironment = new (_environment || _load_environment()).default(scope, directory);
            _context2.prev = 10;
            _context2.next = 13;
            return isolatedEnvironment.create();

          case 13:
            isolateOpts = {
              verbose,
              installPackages: true,
              noPackageJson: false
            };
            _context2.next = 16;
            return isolatedEnvironment.isolateComponent(component.id, isolateOpts);

          case 16:
            componentWithDependencies = _context2.sent;
            isolatedComponent = componentWithDependencies.component;
            _context2.next = 20;
            return _runBuild({
              component,
              componentRoot: isolatedComponent.writtenPath,
              consumer,
              componentMap,
              verbose
            });

          case 20:
            result = _context2.sent;

            if (keep) {
              _context2.next = 24;
              break;
            }

            _context2.next = 24;
            return isolatedEnvironment.destroy();

          case 24:
            return _context2.abrupt('return', result);

          case 27:
            _context2.prev = 27;
            _context2.t0 = _context2['catch'](10);
            _context2.next = 31;
            return isolatedEnvironment.destroy();

          case 31:
            throw _context2.t0;

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

  return function _buildIfNeeded(_x2) {
    return _ref4.apply(this, arguments);
  };
}();

// Ideally it's better to use the dists from the model.
// If there is no consumer, it comes from the scope or isolated environment, which the dists are already saved.
// If there is consumer, check whether the component was modified. If it wasn't, no need to re-build.


var _path;

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

var _fsExtra;

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

var _vinyl;

function _load_vinyl() {
  return _vinyl = _interopRequireDefault(require('vinyl'));
}

var _dists;

function _load_dists() {
  return _dists = _interopRequireDefault(require('../component/sources/dists'));
}

var _consumerComponent;

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

var _scope;

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

var _invalidCompilerInterface;

function _load_invalidCompilerInterface() {
  return _invalidCompilerInterface = _interopRequireDefault(require('../component/exceptions/invalid-compiler-interface'));
}

var _environment;

function _load_environment() {
  return _environment = _interopRequireDefault(require('../../environment'));
}

var _componentMap;

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

var _bitId;

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

var _logger;

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

var _constants;

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

var _externalBuildError;

function _load_externalBuildError() {
  return _externalBuildError = _interopRequireDefault(require('../component/exceptions/external-build-error'));
}

var _consumer;

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

var _utils;

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

var _generalError;

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

var _sources;

function _load_sources() {
  return _sources = require('../component/sources');
}

var _ejectConf;

function _load_ejectConf() {
  return _ejectConf = require('./eject-conf');
}

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 _ref2 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(_ref) {
    var component = _ref.component,
        scope = _ref.scope,
        save = _ref.save,
        consumer = _ref.consumer,
        noCache = _ref.noCache,
        verbose = _ref.verbose,
        keep = _ref.keep;
    var bitMap, consumerPath, componentMap, componentDir, needToRebuild, builtFiles;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            (_logger || _load_logger()).default.debug(`consumer-component.build ${component.id.toString()}`);
            // @TODO - write SourceMap Type

            if (component.compiler) {
              _context.next = 8;
              break;
            }

            if (!(!consumer || consumer.shouldDistsBeInsideTheComponent())) {
              _context.next = 5;
              break;
            }

            (_logger || _load_logger()).default.debug('compiler was not found, nothing to build');
            return _context.abrupt('return', null);

          case 5:
            (_logger || _load_logger()).default.debug('compiler was not found, however, because the dists are set to be outside the components directory, save the source file as dists');
            component.copyFilesIntoDists();
            return _context.abrupt('return', component.dists);

          case 8:
            bitMap = consumer ? consumer.bitMap : undefined;
            consumerPath = consumer ? consumer.getPath() : '';
            componentMap = bitMap && bitMap.getComponentIfExist(component.id);
            componentDir = consumerPath;

            if (componentMap) {
              componentDir = consumerPath && componentMap.rootDir ? (_path || _load_path()).default.join(consumerPath, componentMap.rootDir) : undefined;
            }
            _context.next = 15;
            return _isNeededToReBuild(consumer, component.id, noCache);

          case 15:
            needToRebuild = _context.sent;

            if (!(!needToRebuild && !component.dists.isEmpty())) {
              _context.next = 20;
              break;
            }

            (_logger || _load_logger()).default.debug('skip the build process as the component was not modified, use the dists saved in the model');
            if (componentMap && componentMap.origin === (_constants || _load_constants()).COMPONENT_ORIGINS.IMPORTED) {
              component.stripOriginallySharedDir(bitMap);
              // don't worry about the dist.entry and dist.target at component point. It'll be done later on once the files are
              // written, probably by component.dists.writeDists()
            }

            return _context.abrupt('return', component.dists);

          case 20:
            (_logger || _load_logger()).default.debug('compiler found, start building');

            if (!(component.compiler && !component.compiler.loaded)) {
              _context.next = 24;
              break;
            }

            _context.next = 24;
            return component.compiler.install(scope, { verbose: !!verbose }, { workspaceDir: consumerPath, componentDir, dependentId: component.id });

          case 24:
            _context.next = 26;
            return _buildIfNeeded({
              component,
              consumer,
              componentMap,
              scope,
              keep,
              verbose: !!verbose
            });

          case 26:
            _context.t0 = _context.sent;

            if (_context.t0) {
              _context.next = 29;
              break;
            }

            _context.t0 = [];

          case 29:
            builtFiles = _context.t0;

            // return buildFilesP.then((buildedFiles) => {
            builtFiles.forEach(function (file) {
              if (file && (!file.contents || !(0, (_utils || _load_utils()).isString)(file.contents.toString()))) {
                throw new (_generalError || _load_generalError()).default('builder interface has to return object with a code attribute that contains string');
              }
            });
            component.setDists(builtFiles.map(function (file) {
              return new (_sources || _load_sources()).Dist(file);
            }));

            if (!save) {
              _context.next = 35;
              break;
            }

            _context.next = 35;
            return scope.sources.updateDist({ source: component });

          case 35:
            return _context.abrupt('return', component.dists);

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

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

  return buildComponent;
}();

var _isNeededToReBuild = function () {
  var _ref5 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(consumer, componentId, noCache) {
    var componentStatus;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            if (!noCache) {
              _context3.next = 2;
              break;
            }

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

          case 2:
            if (consumer) {
              _context3.next = 4;
              break;
            }

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

          case 4:
            _context3.next = 6;
            return consumer.getComponentStatusById(componentId);

          case 6:
            componentStatus = _context3.sent;
            return _context3.abrupt('return', componentStatus.modified);

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

  return function _isNeededToReBuild(_x3, _x4, _x5) {
    return _ref5.apply(this, arguments);
  };
}();

var _runBuild = function () {
  var _ref7 = _asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5(_ref6) {
    var component = _ref6.component,
        componentRoot = _ref6.componentRoot,
        consumer = _ref6.consumer,
        componentMap = _ref6.componentMap,
        verbose = _ref6.verbose;
    var compiler, rootDistDir, consumerPath, files, tmpFolderFullPath, componentDir;
    return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
      while (1) {
        switch (_context5.prev = _context5.next) {
          case 0:
            compiler = component.compiler;

            if (compiler) {
              _context5.next = 3;
              break;
            }

            throw new (_generalError || _load_generalError()).default('compiler was not found, nothing to build');

          case 3:
            rootDistDir = (_path || _load_path()).default.join(componentRoot, (_constants || _load_constants()).DEFAULT_DIST_DIRNAME);
            consumerPath = consumer ? consumer.getPath() : '';
            files = component.files.map(function (file) {
              return file.clone();
            });
            tmpFolderFullPath = void 0;
            componentDir = '';

            if (componentMap) {
              // $FlowFixMe
              rootDistDir = component.dists.getDistDirForConsumer(consumer, componentMap.rootDir);
              if (consumerPath && componentMap && componentMap.getComponentDir()) {
                componentDir = componentMap.getComponentDir() || '';
              }
            }
            return _context5.abrupt('return', Promise.resolve().then(_asyncToGenerator( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4() {
              var context, shouldWriteConfig, actionParams, result;
              return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
                while (1) {
                  switch (_context4.prev = _context4.next) {
                    case 0:
                      if (!(!compiler.action && !compiler.oldAction)) {
                        _context4.next = 2;
                        break;
                      }

                      throw new (_invalidCompilerInterface || _load_invalidCompilerInterface()).default(compiler.name);

                    case 2:
                      context = {
                        componentObject: component.toObject(),
                        rootDistDir,
                        componentDir
                      };

                      // Change the cwd to make sure we found the needed files

                      process.chdir(componentRoot);

                      if (!compiler.action) {
                        _context4.next = 22;
                        break;
                      }

                      shouldWriteConfig = compiler.writeConfigFilesOnAction && component.getDetachedCompiler();
                      // Write config files to tmp folder

                      if (!shouldWriteConfig) {
                        _context4.next = 11;
                        break;
                      }

                      tmpFolderFullPath = component.getTmpFolder(consumerPath);
                      if (verbose) {
                        console.log(`\nwriting config files to ${tmpFolderFullPath}`); // eslint-disable-line no-console
                      }
                      _context4.next = 11;
                      return (0, (_ejectConf || _load_ejectConf()).writeEnvFiles)({
                        fullConfigDir: tmpFolderFullPath,
                        env: compiler,
                        consumer,
                        component,
                        deleteOldFiles: false,
                        verbose
                      });

                    case 11:
                      actionParams = {
                        files,
                        rawConfig: compiler.rawConfig,
                        dynamicConfig: compiler.dynamicConfig,
                        configFiles: compiler.files,
                        api: compiler.api,
                        context
                      };
                      _context4.next = 14;
                      return compiler.action(actionParams);

                    case 14:
                      result = _context4.sent;

                      if (!tmpFolderFullPath) {
                        _context4.next = 19;
                        break;
                      }

                      if (verbose) {
                        console.log(`\ndeleting tmp directory ${tmpFolderFullPath}`); // eslint-disable-line no-console
                      }
                      _context4.next = 19;
                      return (_fsExtra || _load_fsExtra()).default.remove(tmpFolderFullPath);

                    case 19:
                      if (!(!result || !result.files)) {
                        _context4.next = 21;
                        break;
                      }

                      throw new Error('compiler return invalid response');

                    case 21:
                      return _context4.abrupt('return', result.files);

                    case 22:
                      if (compiler.oldAction) {
                        _context4.next = 24;
                        break;
                      }

                      throw new (_invalidCompilerInterface || _load_invalidCompilerInterface()).default(compiler.name);

                    case 24:
                      return _context4.abrupt('return', compiler.oldAction(files, rootDistDir, context));

                    case 25:
                    case 'end':
                      return _context4.stop();
                  }
                }
              }, _callee4, undefined);
            }))).catch(function (e) {
              if (tmpFolderFullPath) {
                (_fsExtra || _load_fsExtra()).default.removeSync(tmpFolderFullPath);
              }
              throw new (_externalBuildError || _load_externalBuildError()).default(e, component.id.toString());
            }));

          case 10:
          case 'end':
            return _context5.stop();
        }
      }
    }, _callee5, undefined);
  }));

  return function _runBuild(_x6) {
    return _ref7.apply(this, arguments);
  };
}();