'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.EMPTY_ARRAY = undefined;
exports.createProps = createProps;

var _seerIntegration = require('../lib/seer-integration');

var _log = require('../utils/log');

var _log2 = _interopRequireDefault(_log);

var _propTypes = require('./prop-types');

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

var EMPTY_ARRAY = exports.EMPTY_ARRAY = Object.freeze([]);

// Create a property object
function createProps() {
  var layer = this; // eslint-disable-line

  // Get default prop object (a prototype chain for now)

  var _getPropDefs = getPropDefs(layer.constructor),
      defaultProps = _getPropDefs.defaultProps;

  // Create a new prop object with  default props object in prototype chain


  var newProps = Object.create(defaultProps, {
    _layer: {
      enumerable: false,
      value: layer
    },
    _asyncProps: {
      enumerable: false,
      value: {}
    }
  });

  // "Copy" all sync props
  for (var i = 0; i < arguments.length; ++i) {
    Object.assign(newProps, arguments[i]);
  }
  newProps.data = newProps.data || EMPTY_ARRAY;

  // SEER: Apply any overrides from the seer debug extension if it is active
  (0, _seerIntegration.applyPropOverrides)(newProps);

  // Props must be immutable
  Object.freeze(newProps);

  return newProps;
}

// Helper methods

// Constructors have their super class constructors as prototypes
function getOwnProperty(object, prop) {
  return Object.prototype.hasOwnProperty.call(object, prop) && object[prop];
}

function getLayerName(layerClass) {
  var layerName = getOwnProperty(layerClass, 'layerName');
  if (!layerName) {
    _log2.default.once(0, layerClass.name + '.layerName not specified');
  }
  return layerName || layerClass.name;
}

// Return precalculated defaultProps and propType objects if available
// build them if needed
function getPropDefs(layerClass) {
  var props = getOwnProperty(layerClass, '_mergedDefaultProps');
  if (props) {
    return {
      defaultProps: props,
      propTypes: getOwnProperty(layerClass, '_propTypes')
    };
  }

  return buildPropDefs(layerClass);
}

// Build defaultProps and propType objects by walking layer prototype chain
function buildPropDefs(layerClass) {
  var parent = layerClass.prototype;
  if (!parent) {
    return {
      defaultProps: {}
    };
  }

  var parentClass = Object.getPrototypeOf(layerClass);
  var parentPropDefs = parent && getPropDefs(parentClass) || null;

  // Parse propTypes from Layer.defaultProps
  var layerDefaultProps = getOwnProperty(layerClass, 'defaultProps') || {};
  var layerPropDefs = (0, _propTypes.parsePropTypes)(layerDefaultProps);

  // Create a merged type object
  var propTypes = Object.assign({}, parentPropDefs && parentPropDefs.propTypes, layerPropDefs.propTypes);

  // Create any necessary property descriptors and create the default prop object
  // Assign merged default props
  var defaultProps = buildDefaultProps(layerPropDefs.defaultProps, parentPropDefs && parentPropDefs.defaultProps, propTypes, layerClass);

  // Store the precalculated props
  layerClass._mergedDefaultProps = defaultProps;
  layerClass._propTypes = propTypes;

  return { propTypes: propTypes, defaultProps: defaultProps };
}

function buildDefaultProps(props, parentProps, propTypes, layerClass) {
  var defaultProps = Object.create(null);

  Object.assign(defaultProps, parentProps, props);

  var descriptors = {};

  var id = getLayerName(layerClass);
  delete props.id;

  Object.assign(descriptors, {
    id: {
      configurable: false,
      writable: true,
      value: id
    }
  });

  Object.defineProperties(defaultProps, descriptors);

  return defaultProps;
}
//# sourceMappingURL=create-props.js.map