'use strict';

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

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 _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 _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _ramda;

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

var _abstractConfig;

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

var _generalError;

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

var _filterObject;

function _load_filterObject() {
  return _filterObject = _interopRequireDefault(require('../../utils/filter-object'));
}

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

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

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var ComponentConfig = function (_AbstractConfig) {
  _inherits(ComponentConfig, _AbstractConfig);

  // whether a component has bit.json written to FS or package.json written with 'bit' property
  function ComponentConfig(_ref) {
    var compiler = _ref.compiler,
        tester = _ref.tester,
        lang = _ref.lang,
        bindingPrefix = _ref.bindingPrefix,
        extensions = _ref.extensions,
        overrides = _ref.overrides;

    _classCallCheck(this, ComponentConfig);

    var _this = _possibleConstructorReturn(this, (ComponentConfig.__proto__ || Object.getPrototypeOf(ComponentConfig)).call(this, {
      compiler,
      tester,
      lang,
      bindingPrefix,
      extensions
    }));

    _this.componentHasWrittenConfig = false;

    _this.overrides = overrides;
    _this.writeToBitJson = true; // will be changed later to work similar to workspace-config
    return _this;
  }

  _createClass(ComponentConfig, [{
    key: 'toPlainObject',
    value: function toPlainObject() {
      var superObject = _get(ComponentConfig.prototype.__proto__ || Object.getPrototypeOf(ComponentConfig.prototype), 'toPlainObject', this).call(this);
      var componentObject = (_ramda || _load_ramda()).default.merge(superObject, {
        overrides: this.overrides
      });
      var isPropDefaultOrEmpty = function isPropDefaultOrEmpty(val, key) {
        if (key === 'overrides') return !(_ramda || _load_ramda()).default.isEmpty(val);
        return true;
      };
      return (0, (_filterObject || _load_filterObject()).default)(componentObject, isPropDefaultOrEmpty);
    }
  }, {
    key: 'validate',
    value: function validate(bitJsonPath) {
      if (typeof this.compiler !== 'object' || typeof this.tester !== 'object' || this.extensions() && typeof this.extensions() !== 'object') {
        throw new (_generalError || _load_generalError()).default(`bit.json at "${bitJsonPath}" is invalid, re-import the component with "--conf" flag to recreate it`);
      }
    }
  }, {
    key: 'mergeWithComponentData',
    value: function mergeWithComponentData(component) {
      this.bindingPrefix = this.bindingPrefix || component.bindingPrefix;
      this.lang = this.lang || component.lang;
    }

    /**
     * Use the workspaceConfig as a base. Override values if exist in componentConfig
     */

  }], [{
    key: 'fromPlainObject',
    value: function fromPlainObject(object) {
      var env = object.env,
          lang = object.lang,
          bindingPrefix = object.bindingPrefix,
          extensions = object.extensions,
          overrides = object.overrides;


      return new ComponentConfig({
        compiler: (_ramda || _load_ramda()).default.prop('compiler', env),
        tester: (_ramda || _load_ramda()).default.prop('tester', env),
        extensions,
        lang,
        bindingPrefix,
        overrides
      });
    }
  }, {
    key: 'fromComponent',
    value: function fromComponent(component) {
      return new ComponentConfig({
        version: component.version,
        scope: component.scope,
        lang: component.lang,
        bindingPrefix: component.bindingPrefix,
        compiler: component.compiler || {},
        tester: component.tester || {},
        overrides: component.overrides.componentOverridesData
      });
    }
  }, {
    key: 'mergeWithWorkspaceConfig',
    value: function mergeWithWorkspaceConfig(componentConfig, consumerConfig) {
      var plainConsumerConfig = consumerConfig ? consumerConfig.toPlainObject() : {};
      return ComponentConfig.fromPlainObject((_ramda || _load_ramda()).default.merge(plainConsumerConfig, componentConfig));
    }

    /**
     * component config is written by default to package.json inside "bit" property.
     * in case "eject-conf" was running or the component was imported with "--conf" flag, the
     * bit.json is written as well.
     *
     * @param {*} componentDir root component directory, needed for loading package.json file.
     * in case a component is authored, leave this param empty to not load the project package.json
     * @param {*} configDir dir where bit.json and other envs files are written (by eject-conf or import --conf)
     * @param {*} consumerConfig
     */

  }, {
    key: 'load',
    value: function () {
      var _ref2 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(componentDir, configDir, consumerConfig) {
        var _this2 = this;

        var bitJsonPath, packageJsonPath, loadBitJson, loadPackageJson, _ref5, _ref6, bitJsonFile, packageJsonFile, bitJsonConfig, packageJsonHasConfig, packageJsonConfig, config, componentConfig;

        return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                if (configDir) {
                  _context3.next = 2;
                  break;
                }

                throw new TypeError('component-config.load configDir arg is empty');

              case 2:
                bitJsonPath = (_abstractConfig || _load_abstractConfig()).default.composeBitJsonPath(configDir);
                packageJsonPath = componentDir ? (_abstractConfig || _load_abstractConfig()).default.composePackageJsonPath(componentDir) : null;

                loadBitJson = function () {
                  var _ref3 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee() {
                    var file;
                    return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
                      while (1) {
                        switch (_context.prev = _context.next) {
                          case 0:
                            _context.prev = 0;
                            _context.next = 3;
                            return (_abstractConfig || _load_abstractConfig()).default.loadJsonFileIfExist(bitJsonPath);

                          case 3:
                            file = _context.sent;
                            return _context.abrupt('return', file);

                          case 7:
                            _context.prev = 7;
                            _context.t0 = _context['catch'](0);
                            throw new (_generalError || _load_generalError()).default(`bit.json at "${bitJsonPath}" is not a valid JSON file, re-import the component with "--conf" flag to recreate it`);

                          case 10:
                          case 'end':
                            return _context.stop();
                        }
                      }
                    }, _callee, _this2, [[0, 7]]);
                  }));

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

                loadPackageJson = function () {
                  var _ref4 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2() {
                    var file;
                    return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
                      while (1) {
                        switch (_context2.prev = _context2.next) {
                          case 0:
                            if (packageJsonPath) {
                              _context2.next = 2;
                              break;
                            }

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

                          case 2:
                            _context2.prev = 2;
                            _context2.next = 5;
                            return (_abstractConfig || _load_abstractConfig()).default.loadJsonFileIfExist(packageJsonPath);

                          case 5:
                            file = _context2.sent;
                            return _context2.abrupt('return', file);

                          case 9:
                            _context2.prev = 9;
                            _context2.t0 = _context2['catch'](2);
                            throw new (_generalError || _load_generalError()).default(`package.json at ${packageJsonPath} is not a valid JSON file, consider to re-import the file to re-generate the file`);

                          case 12:
                          case 'end':
                            return _context2.stop();
                        }
                      }
                    }, _callee2, _this2, [[2, 9]]);
                  }));

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

                _context3.next = 8;
                return Promise.all([loadBitJson(), loadPackageJson()]);

              case 8:
                _ref5 = _context3.sent;
                _ref6 = _slicedToArray(_ref5, 2);
                bitJsonFile = _ref6[0];
                packageJsonFile = _ref6[1];
                bitJsonConfig = bitJsonFile || {};
                packageJsonHasConfig = Boolean(packageJsonFile && packageJsonFile.bit);
                packageJsonConfig = packageJsonHasConfig ? packageJsonFile.bit : {};
                // in case of conflicts, bit.json wins package.json

                config = Object.assign(packageJsonConfig, bitJsonConfig);
                componentConfig = ComponentConfig.mergeWithWorkspaceConfig(config, consumerConfig);

                componentConfig.path = bitJsonPath;
                componentConfig.componentHasWrittenConfig = packageJsonHasConfig || Boolean(bitJsonFile);
                componentConfig.packageJsonObject = packageJsonFile;
                return _context3.abrupt('return', componentConfig);

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

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

      return load;
    }()
  }]);

  return ComponentConfig;
}((_abstractConfig || _load_abstractConfig()).default);

exports.default = ComponentConfig;