'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 _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 _path;

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

var _ramda;

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

var _ramdaAdjunct;

function _load_ramdaAdjunct() {
  return _ramdaAdjunct = _interopRequireWildcard(require('ramda-adjunct'));
}

var _fsExtra;

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

var _bitId;

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

var _utils;

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

var _constants;

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

var _logger;

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

var _jsonFile;

function _load_jsonFile() {
  return _jsonFile = _interopRequireDefault(require('../component/sources/json-file'));
}

var _packageJsonFile;

function _load_packageJsonFile() {
  return _packageJsonFile = _interopRequireDefault(require('../component/package-json-file'));
}

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

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

/**
 * There are two Bit Config: WorkspaceConfig and ComponentConfig, both inherit this class.
 * The config data can be written in package.json inside "bit" property. And, can be written in
 * bit.json file. Also, it might be written in both, in which case, if there is any conflict, the
 * bit.json wins.
 */
var AbstractConfig = function () {
  function AbstractConfig(props) {
    _classCallCheck(this, AbstractConfig);

    this.writeToPackageJson = false;
    this.writeToBitJson = false;

    this._compiler = props.compiler || {};
    this._tester = props.tester || {};
    this.lang = props.lang || (_constants || _load_constants()).DEFAULT_LANGUAGE;
    this.bindingPrefix = props.bindingPrefix || (_constants || _load_constants()).DEFAULT_BINDINGS_PREFIX;
    this.extensions = props.extensions || (_constants || _load_constants()).DEFAULT_EXTENSIONS;
  }

  _createClass(AbstractConfig, [{
    key: 'addDependencies',
    value: function addDependencies(bitIds) {
      var idObjects = (_ramda || _load_ramda()).default.mergeAll(bitIds.map(function (bitId) {
        return bitId.toObject();
      }));
      this.dependencies = (_ramda || _load_ramda()).default.merge(this.dependencies, idObjects);
      return this;
    }
  }, {
    key: 'addDependency',
    value: function addDependency(bitId) {
      this.dependencies = (_ramda || _load_ramda()).default.merge(this.dependencies, bitId.toObject());
      return this;
    }
  }, {
    key: 'hasCompiler',
    value: function hasCompiler() {
      return !!this.compiler && this._compiler !== (_constants || _load_constants()).NO_PLUGIN_TYPE && !(_ramda || _load_ramda()).default.isEmpty(this.compiler);
    }
  }, {
    key: 'hasTester',
    value: function hasTester() {
      return !!this.tester && this._tester !== (_constants || _load_constants()).NO_PLUGIN_TYPE && !(_ramda || _load_ramda()).default.isEmpty(this.tester);
    }
  }, {
    key: 'getEnvsByType',
    value: function getEnvsByType(type) {
      if (type === (_constants || _load_constants()).COMPILER_ENV_TYPE) {
        return this.compiler;
      }
      return this.tester;
    }

    /**
     * if there is only one env (compiler/tester) and it doesn't have any special configuration, only
     * the name, convert it to a string.
     */

  }, {
    key: 'getDependencies',
    value: function getDependencies() {
      return (_bitId || _load_bitId()).BitIds.fromObject(this.dependencies);
    }
  }, {
    key: 'toPlainObject',
    value: function toPlainObject() {
      var isPropDefaultOrNull = function isPropDefaultOrNull(val, key) {
        if (!val) return false;
        if (key === 'lang') return val !== (_constants || _load_constants()).DEFAULT_LANGUAGE;
        if (key === 'bindingPrefix') return val !== (_constants || _load_constants()).DEFAULT_BINDINGS_PREFIX;
        if (key === 'extensions') return !(_ramda || _load_ramda()).default.equals(val, (_constants || _load_constants()).DEFAULT_EXTENSIONS);
        return true;
      };

      return (0, (_utils || _load_utils()).filterObject)({
        lang: this.lang,
        bindingPrefix: this.bindingPrefix,
        env: {
          compiler: AbstractConfig.convertEnvToStringIfPossible(this.compiler),
          tester: AbstractConfig.convertEnvToStringIfPossible(this.tester)
        },
        dependencies: this.dependencies,
        extensions: this.extensions
      }, isPropDefaultOrNull);
    }
  }, {
    key: 'write',
    value: function () {
      var _ref = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee(_ref2) {
        var bitDir = _ref2.bitDir;
        var jsonFiles;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _context.next = 2;
                return this.prepareToWrite({ bitDir });

              case 2:
                jsonFiles = _context.sent;
                return _context.abrupt('return', Promise.all(jsonFiles.map(function (jsonFile) {
                  return jsonFile.write();
                })));

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

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

      return write;
    }()
  }, {
    key: 'prepareToWrite',
    value: function () {
      var _ref3 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee2(_ref4) {
        var bitDir = _ref4.bitDir;
        var plainObject, JsonFiles, addJsonFile, packageJsonFile, bitJsonPath;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                plainObject = this.toPlainObject();
                JsonFiles = [];

                addJsonFile = function addJsonFile(pathStr, content) {
                  var params = { base: bitDir, override: true, path: pathStr, content };
                  JsonFiles.push((_jsonFile || _load_jsonFile()).default.load(params));
                };

                if (!this.writeToPackageJson) {
                  _context2.next = 9;
                  break;
                }

                _context2.next = 6;
                return (_packageJsonFile || _load_packageJsonFile()).default.load(bitDir);

              case 6:
                packageJsonFile = _context2.sent;

                packageJsonFile.addOrUpdateProperty('bit', plainObject);
                JsonFiles.push(packageJsonFile.toJSONFile());

              case 9:
                if (this.writeToBitJson) {
                  bitJsonPath = AbstractConfig.composeBitJsonPath(bitDir);

                  addJsonFile(bitJsonPath, plainObject);
                }
                return _context2.abrupt('return', JsonFiles);

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

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

      return prepareToWrite;
    }()
  }, {
    key: 'compiler',
    get: function get() {
      var compilerObj = AbstractConfig.transformEnvToObject(this._compiler);
      if ((_ramda || _load_ramda()).default.isEmpty(compilerObj)) return undefined;
      return compilerObj;
    },
    set: function set(compiler) {
      this._compiler = AbstractConfig.transformEnvToObject(compiler);
    }
  }, {
    key: 'tester',
    get: function get() {
      var testerObj = AbstractConfig.transformEnvToObject(this._tester);
      if ((_ramda || _load_ramda()).default.isEmpty(testerObj)) return undefined;
      return testerObj;
    },
    set: function set(tester) {
      this._tester = AbstractConfig.transformEnvToObject(tester);
    }
  }], [{
    key: 'convertEnvToStringIfPossible',
    value: function convertEnvToStringIfPossible(envObj) {
      if (!envObj) return undefined;
      if (Object.keys(envObj).length !== 1) return envObj; // it has more than one id
      var envId = Object.keys(envObj)[0];
      if ((_ramdaAdjunct || _load_ramdaAdjunct()).isNilOrEmpty(envObj[envId].rawConfig) && (_ramdaAdjunct || _load_ramdaAdjunct()).isNilOrEmpty(envObj[envId].options) && (_ramdaAdjunct || _load_ramdaAdjunct()).isNilOrEmpty(envObj[envId].files)) {
        return envId;
      }
      return envObj;
    }
  }, {
    key: 'composeBitJsonPath',
    value: function composeBitJsonPath(bitPath) {
      return (_path || _load_path()).default.join(bitPath, (_constants || _load_constants()).BIT_JSON);
    }
  }, {
    key: 'composePackageJsonPath',
    value: function composePackageJsonPath(bitPath) {
      return (_path || _load_path()).default.join(bitPath, (_constants || _load_constants()).PACKAGE_JSON);
    }
  }, {
    key: 'pathHasBitJson',
    value: function () {
      var _ref5 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee3(bitPath) {
        return (_regenerator || _load_regenerator()).default.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                return _context3.abrupt('return', (_fsExtra || _load_fsExtra()).default.exists(this.composeBitJsonPath(bitPath)));

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

      function pathHasBitJson(_x3) {
        return _ref5.apply(this, arguments);
      }

      return pathHasBitJson;
    }()
  }, {
    key: 'pathHasPackageJson',
    value: function () {
      var _ref6 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee4(bitPath) {
        return (_regenerator || _load_regenerator()).default.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                return _context4.abrupt('return', (_fsExtra || _load_fsExtra()).default.exists(this.composePackageJsonPath(bitPath)));

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

      function pathHasPackageJson(_x4) {
        return _ref6.apply(this, arguments);
      }

      return pathHasPackageJson;
    }()
  }, {
    key: 'loadJsonFileIfExist',
    value: function () {
      var _ref7 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee5(jsonFilePath) {
        var file;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                _context5.prev = 0;
                _context5.next = 3;
                return (_fsExtra || _load_fsExtra()).default.readJson(jsonFilePath);

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

              case 7:
                _context5.prev = 7;
                _context5.t0 = _context5['catch'](0);

                if (!(_context5.t0.code === 'ENOENT')) {
                  _context5.next = 11;
                  break;
                }

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

              case 11:
                throw _context5.t0;

              case 12:
              case 'end':
                return _context5.stop();
            }
          }
        }, _callee5, this, [[0, 7]]);
      }));

      function loadJsonFileIfExist(_x5) {
        return _ref7.apply(this, arguments);
      }

      return loadJsonFileIfExist;
    }()
  }, {
    key: 'removeIfExist',
    value: function () {
      var _ref8 = (0, (_bluebird || _load_bluebird()).coroutine)( /*#__PURE__*/(_regenerator || _load_regenerator()).default.mark(function _callee6(bitPath) {
        var dirToRemove;
        return (_regenerator || _load_regenerator()).default.wrap(function _callee6$(_context6) {
          while (1) {
            switch (_context6.prev = _context6.next) {
              case 0:
                dirToRemove = this.composeBitJsonPath(bitPath);

                if (!(_fsExtra || _load_fsExtra()).default.exists(dirToRemove)) {
                  _context6.next = 4;
                  break;
                }

                (_logger || _load_logger()).default.info(`abstract-config, deleting ${dirToRemove}`);
                return _context6.abrupt('return', (_fsExtra || _load_fsExtra()).default.remove(dirToRemove));

              case 4:
                return _context6.abrupt('return', false);

              case 5:
              case 'end':
                return _context6.stop();
            }
          }
        }, _callee6, this);
      }));

      function removeIfExist(_x6) {
        return _ref8.apply(this, arguments);
      }

      return removeIfExist;
    }()
  }, {
    key: 'transformEnvToObject',
    value: function transformEnvToObject(env) {
      if (typeof env === 'string') {
        if (env === (_constants || _load_constants()).NO_PLUGIN_TYPE) return {};
        return {
          [env]: {}
        };
      }
      return env;
    }
  }]);

  return AbstractConfig;
}();

exports.default = AbstractConfig;