"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = void 0;

var _fs = _interopRequireDefault(require("fs"));

var _path = _interopRequireDefault(require("path"));

var _memFs = _interopRequireDefault(require("mem-fs"));

var _memFsEditor = _interopRequireDefault(require("mem-fs-editor"));

var _chalk = _interopRequireDefault(require("chalk"));

var _rxjs = require("rxjs");

var _constants = require("../constants");

var _config = _interopRequireDefault(require("../config"));

var _installerError = _interopRequireDefault(require("./installer-error"));

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

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

var Installer =
/*#__PURE__*/
function () {
  /**
   * mongoose-data-seed installer
   * @param {String} seedersFolder              Relative path to your seeders-folder
   * @param {String} customSeederTemplate       Relative path to your seeder-template
   *                                            if you would like to use your own seeders-template
   */
  function Installer() {
    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _constants.defaultUserGeneratorConfig,
        seedersFolder = _ref.seedersFolder,
        customSeederTemplate = _ref.customSeederTemplate;

    _classCallCheck(this, Installer);

    this.subject = new _rxjs.Subject();

    this._initConfig({
      seedersFolder: seedersFolder,
      customSeederTemplate: customSeederTemplate
    });

    this._initMemFs();
  }
  /**
   * Run installer - install `mongoose-data-seeder`
   * @return {Observable}
   */


  _createClass(Installer, [{
    key: "install",
    value: function install() {
      this._install();

      return this.subject.asObservable();
    }
    /**
     * config to write into the `package.json`
     */

  }, {
    key: "getGeneratorConfig",
    value: function getGeneratorConfig() {
      var _this$config = this.config,
          seedersFolder = _this$config.userSeedersFolderName,
          customSeederTemplate = _this$config.customSeederTemplateFilename;
      var generatorConfig = {
        seedersFolder: seedersFolder
      };

      if (customSeederTemplate) {
        generatorConfig.customSeederTemplate = customSeederTemplate;
      }

      return generatorConfig;
    }
    /*
      Private methods
     */

    /**
     * Initiate this.config
     * @param {String} seedersFolder              Relative path to your seeders-folder
     * @param {String} customSeederTemplate       Relative path to your seeder-template
     *                                            if you would like to use your own seeders-template
     */

  }, {
    key: "_initConfig",
    value: function _initConfig(_ref2) {
      var seedersFolder = _ref2.seedersFolder,
          customSeederTemplate = _ref2.customSeederTemplate;
      this.config = {
        userPackageJsonPath: _path["default"].join(_config["default"].projectRoot, './package.json'),
        customSeederTemplateFilename: customSeederTemplate,
        customSeederTemplatePath: customSeederTemplate && _path["default"].join(_config["default"].projectRoot, customSeederTemplate),
        userSeedersFolderName: seedersFolder,
        userSeedersFolderPath: _path["default"].join(_config["default"].projectRoot, seedersFolder),
        userConfigExists: _config["default"].userConfigExists,
        userConfigFilename: _config["default"].userConfigFilename,
        userConfigFilepath: _config["default"].userConfigFilepath,
        configTemplatePath: _config["default"].configTemplate
      };
    }
    /**
     * Initiate the in-memory file-system
     */

  }, {
    key: "_initMemFs",
    value: function _initMemFs() {
      var store = _memFs["default"].create();

      this.memFsEditor = _memFsEditor["default"].create(store);
    }
    /**
     * Run the installation process
     * @return {Promise}
     */

  }, {
    key: "_install",
    value: function () {
      var _install2 = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee() {
        var _Installer$operations, START, SUCCESS, ERROR, _error$type, type, _error$payload, payload;

        return regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _Installer$operations = Installer.operations, START = _Installer$operations.START, SUCCESS = _Installer$operations.SUCCESS, ERROR = _Installer$operations.ERROR;
                _context.prev = 1;
                this.subject.next({
                  type: START
                });
                _context.next = 5;
                return this._createCustomSeederTemplate();

              case 5:
                _context.next = 7;
                return this._writeUserGeneratorConfigToPackageJson();

              case 7:
                _context.next = 9;
                return this._createSeedersFolder();

              case 9:
                _context.next = 11;
                return this._writeUserConfig();

              case 11:
                this.subject.next({
                  type: SUCCESS
                });
                this.subject.complete();
                _context.next = 19;
                break;

              case 15:
                _context.prev = 15;
                _context.t0 = _context["catch"](1);
                _error$type = _context.t0.type, type = _error$type === void 0 ? ERROR : _error$type, _error$payload = _context.t0.payload, payload = _error$payload === void 0 ? {
                  error: _context.t0
                } : _error$payload;
                this.subject.error({
                  type: type,
                  payload: payload
                });

              case 19:
              case "end":
                return _context.stop();
            }
          }
        }, _callee, this, [[1, 15]]);
      }));

      function _install() {
        return _install2.apply(this, arguments);
      }

      return _install;
    }()
    /**
     * Commit the in-memory file changes
     * @return {Promise}
     */

  }, {
    key: "_commitMemFsChanges",
    value: function () {
      var _commitMemFsChanges2 = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee2() {
        var _this = this;

        return regeneratorRuntime.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                return _context2.abrupt("return", new Promise(function (resolve) {
                  _this.memFsEditor.commit(function () {
                    resolve();
                  });
                }));

              case 1:
              case "end":
                return _context2.stop();
            }
          }
        }, _callee2);
      }));

      function _commitMemFsChanges() {
        return _commitMemFsChanges2.apply(this, arguments);
      }

      return _commitMemFsChanges;
    }()
    /**
     * Copy the package seeder-template to the user desired
     * custom-seeder-template path if the user wants to use his own seeder-template
     * @return {Promise} [description]
     */

  }, {
    key: "_createCustomSeederTemplate",
    value: function () {
      var _createCustomSeederTemplate2 = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee3() {
        var _this2 = this;

        var _Installer$operations2, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_START, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SUCCESS, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_ERROR, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_FILE_EXISTS, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_NO_CUSTOM, _this$config2, customSeederTemplateFilename, customSeederTemplatePath, payload, notify;

        return regeneratorRuntime.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                _Installer$operations2 = Installer.operations, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_START = _Installer$operations2.CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_START, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SUCCESS = _Installer$operations2.CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SUCCESS, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_ERROR = _Installer$operations2.CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_ERROR, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_FILE_EXISTS = _Installer$operations2.CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_FILE_EXISTS, CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_NO_CUSTOM = _Installer$operations2.CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_NO_CUSTOM;
                _this$config2 = this.config, customSeederTemplateFilename = _this$config2.customSeederTemplateFilename, customSeederTemplatePath = _this$config2.customSeederTemplatePath;
                payload = {
                  customSeederTemplateFilename: customSeederTemplateFilename,
                  customSeederTemplatePath: customSeederTemplatePath
                };

                notify = function notify(type) {
                  return _this2.subject.next({
                    type: type,
                    payload: payload
                  });
                };

                _context3.prev = 4;
                notify(CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_START);

                if (customSeederTemplatePath) {
                  _context3.next = 8;
                  break;
                }

                return _context3.abrupt("return", notify(CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_NO_CUSTOM));

              case 8:
                if (!_fs["default"].existsSync(customSeederTemplatePath)) {
                  _context3.next = 12;
                  break;
                }

                notify(CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_FILE_EXISTS);
                _context3.next = 16;
                break;

              case 12:
                // copy template
                this.memFsEditor.copy(_constants.systemSeederTemplate, customSeederTemplatePath); // commit changes

                _context3.next = 15;
                return this._commitMemFsChanges();

              case 15:
                notify(CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SUCCESS);

              case 16:
                _context3.next = 21;
                break;

              case 18:
                _context3.prev = 18;
                _context3.t0 = _context3["catch"](4);
                throw new _installerError["default"]({
                  type: CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_ERROR,
                  payload: payload,
                  error: _context3.t0
                });

              case 21:
              case "end":
                return _context3.stop();
            }
          }
        }, _callee3, this, [[4, 18]]);
      }));

      function _createCustomSeederTemplate() {
        return _createCustomSeederTemplate2.apply(this, arguments);
      }

      return _createCustomSeederTemplate;
    }()
    /**
     * Write the config into the user package.json
     */

  }, {
    key: "_writeUserGeneratorConfigToPackageJson",
    value: function () {
      var _writeUserGeneratorConfigToPackageJson2 = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee4() {
        var _Installer$operations3, WRITE_USER_GENERETOR_CONFIG_START, WRITE_USER_GENERETOR_CONFIG_SUCCESS, WRITE_USER_GENERETOR_CONFIG_ERROR, packageJsonPath, payload, packageJson;

        return regeneratorRuntime.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                _Installer$operations3 = Installer.operations, WRITE_USER_GENERETOR_CONFIG_START = _Installer$operations3.WRITE_USER_GENERETOR_CONFIG_START, WRITE_USER_GENERETOR_CONFIG_SUCCESS = _Installer$operations3.WRITE_USER_GENERETOR_CONFIG_SUCCESS, WRITE_USER_GENERETOR_CONFIG_ERROR = _Installer$operations3.WRITE_USER_GENERETOR_CONFIG_ERROR;
                packageJsonPath = this.config.userPackageJsonPath;
                payload = {
                  packageJsonPath: packageJsonPath
                };
                _context4.prev = 3;
                this.subject.next({
                  type: WRITE_USER_GENERETOR_CONFIG_START,
                  payload: payload
                });
                packageJson = require(packageJsonPath);
                packageJson.mdSeed = this.getGeneratorConfig();
                this.memFsEditor.writeJSON(packageJsonPath, packageJson);
                _context4.next = 10;
                return this._commitMemFsChanges();

              case 10:
                this.subject.next({
                  type: WRITE_USER_GENERETOR_CONFIG_SUCCESS,
                  payload: payload
                });
                _context4.next = 16;
                break;

              case 13:
                _context4.prev = 13;
                _context4.t0 = _context4["catch"](3);
                throw new _installerError["default"]({
                  type: WRITE_USER_GENERETOR_CONFIG_ERROR,
                  payload: payload,
                  error: _context4.t0
                });

              case 16:
              case "end":
                return _context4.stop();
            }
          }
        }, _callee4, this, [[3, 13]]);
      }));

      function _writeUserGeneratorConfigToPackageJson() {
        return _writeUserGeneratorConfigToPackageJson2.apply(this, arguments);
      }

      return _writeUserGeneratorConfigToPackageJson;
    }()
    /**
     * Create the seeders folder
     */

  }, {
    key: "_createSeedersFolder",
    value: function () {
      var _createSeedersFolder2 = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee5() {
        var _Installer$operations4, CREATE_SEEDERS_FOLDER_START, CREATE_SEEDERS_FOLDER_SUCCESS, CREATE_SEEDERS_FOLDER_ERROR, CREATE_SEEDERS_FOLDER_SKIP_FOLDER_EXISTS, _this$config3, folderpath, foldername, payload;

        return regeneratorRuntime.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                _Installer$operations4 = Installer.operations, CREATE_SEEDERS_FOLDER_START = _Installer$operations4.CREATE_SEEDERS_FOLDER_START, CREATE_SEEDERS_FOLDER_SUCCESS = _Installer$operations4.CREATE_SEEDERS_FOLDER_SUCCESS, CREATE_SEEDERS_FOLDER_ERROR = _Installer$operations4.CREATE_SEEDERS_FOLDER_ERROR, CREATE_SEEDERS_FOLDER_SKIP_FOLDER_EXISTS = _Installer$operations4.CREATE_SEEDERS_FOLDER_SKIP_FOLDER_EXISTS;
                _this$config3 = this.config, folderpath = _this$config3.userSeedersFolderPath, foldername = _this$config3.userSeedersFolderName;
                payload = {
                  folderpath: folderpath,
                  foldername: foldername
                };
                _context5.prev = 3;
                this.subject.next({
                  type: CREATE_SEEDERS_FOLDER_START,
                  payload: payload
                });

                if (_fs["default"].existsSync(folderpath)) {
                  this.subject.next({
                    type: CREATE_SEEDERS_FOLDER_SKIP_FOLDER_EXISTS,
                    payload: payload
                  });
                } else {
                  _fs["default"].mkdirSync(folderpath);

                  this.subject.next({
                    type: CREATE_SEEDERS_FOLDER_SUCCESS,
                    payload: payload
                  });
                }

                _context5.next = 11;
                break;

              case 8:
                _context5.prev = 8;
                _context5.t0 = _context5["catch"](3);
                throw new _installerError["default"]({
                  type: CREATE_SEEDERS_FOLDER_ERROR,
                  payload: payload,
                  error: _context5.t0
                });

              case 11:
              case "end":
                return _context5.stop();
            }
          }
        }, _callee5, this, [[3, 8]]);
      }));

      function _createSeedersFolder() {
        return _createSeedersFolder2.apply(this, arguments);
      }

      return _createSeedersFolder;
    }()
    /**
     * Write the `md-seed-config.js` into the root folder
     */

  }, {
    key: "_writeUserConfig",
    value: function () {
      var _writeUserConfig2 = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee6() {
        var _Installer$operations5, WRITE_USER_CONFIG_START, WRITE_USER_CONFIG_SUCCESS, WRITE_USER_CONFIG_ERROR, WRITE_USER_CONFIG_SKIP_FILE_EXISTS, _this$config4, fileExists, filename, filepath, configTemplatePath, payload;

        return regeneratorRuntime.wrap(function _callee6$(_context6) {
          while (1) {
            switch (_context6.prev = _context6.next) {
              case 0:
                _Installer$operations5 = Installer.operations, WRITE_USER_CONFIG_START = _Installer$operations5.WRITE_USER_CONFIG_START, WRITE_USER_CONFIG_SUCCESS = _Installer$operations5.WRITE_USER_CONFIG_SUCCESS, WRITE_USER_CONFIG_ERROR = _Installer$operations5.WRITE_USER_CONFIG_ERROR, WRITE_USER_CONFIG_SKIP_FILE_EXISTS = _Installer$operations5.WRITE_USER_CONFIG_SKIP_FILE_EXISTS;
                _this$config4 = this.config, fileExists = _this$config4.userConfigExists, filename = _this$config4.userConfigFilename, filepath = _this$config4.userConfigFilepath, configTemplatePath = _this$config4.configTemplatePath;
                payload = {
                  fileExists: fileExists,
                  filename: filename,
                  filepath: filepath
                };
                _context6.prev = 3;
                this.subject.next({
                  type: WRITE_USER_CONFIG_START,
                  payload: payload
                });

                if (!(fileExists === true)) {
                  _context6.next = 9;
                  break;
                }

                this.subject.next({
                  type: WRITE_USER_CONFIG_SKIP_FILE_EXISTS,
                  payload: payload
                });
                _context6.next = 13;
                break;

              case 9:
                // copy template
                this.memFsEditor.copy(configTemplatePath, filepath); // commit changes

                _context6.next = 12;
                return this._commitMemFsChanges();

              case 12:
                this.subject.next({
                  type: WRITE_USER_CONFIG_SUCCESS,
                  payload: payload
                });

              case 13:
                _context6.next = 18;
                break;

              case 15:
                _context6.prev = 15;
                _context6.t0 = _context6["catch"](3);
                throw new _installerError["default"]({
                  type: WRITE_USER_CONFIG_ERROR,
                  payload: payload,
                  error: _context6.t0
                });

              case 18:
              case "end":
                return _context6.stop();
            }
          }
        }, _callee6, this, [[3, 15]]);
      }));

      function _writeUserConfig() {
        return _writeUserConfig2.apply(this, arguments);
      }

      return _writeUserConfig;
    }()
  }]);

  return Installer;
}();

exports["default"] = Installer;

_defineProperty(Installer, "operations", {
  START: 'START',
  SUCCESS: 'SUCCESS',
  ERROR: 'ERROR',
  WRITE_USER_GENERETOR_CONFIG_START: 'WRITE_USER_GENERETOR_CONFIG_START',
  WRITE_USER_GENERETOR_CONFIG_SUCCESS: 'WRITE_USER_GENERETOR_CONFIG_SUCCESS',
  WRITE_USER_GENERETOR_CONFIG_ERROR: 'WRITE_USER_GENERETOR_CONFIG_ERROR',
  CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_START: 'CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_START',
  CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SUCCESS: 'CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SUCCESS',
  CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_ERROR: 'CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_ERROR',
  CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_FILE_EXISTS: 'CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_FILE_EXISTS',
  CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_NO_CUSTOM: 'CREATE_CUSTOM_SEEDER_TEMPLATE_FILE_SKIP_NO_CUSTOM',
  CREATE_SEEDERS_FOLDER_START: 'CREATE_SEEDERS_FOLDER_START',
  CREATE_SEEDERS_FOLDER_SUCCESS: 'CREATE_SEEDERS_FOLDER_SUCCESS',
  CREATE_SEEDERS_FOLDER_ERROR: 'CREATE_SEEDERS_FOLDER_ERROR',
  CREATE_SEEDERS_FOLDER_SKIP_FOLDER_EXISTS: 'CREATE_SEEDERS_FOLDER_SKIP_FOLDER_EXISTS',
  WRITE_USER_CONFIG_START: 'WRITE_USER_CONFIG_START',
  WRITE_USER_CONFIG_SUCCESS: 'WRITE_USER_CONFIG_SUCCESS',
  WRITE_USER_CONFIG_ERROR: 'WRITE_USER_CONFIG_ERROR',
  WRITE_USER_CONFIG_SKIP_FILE_EXISTS: 'WRITE_USER_CONFIG_SKIP_FILE_EXISTS'
});