var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

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

import assert from '../utils/assert';

var TYPE_DEFINITIONS = {
  boolean: {
    validate: function validate(value, propType) {
      return true;
    }
  },
  number: {
    validateType: function validateType(value, propType) {
      return 'value' in propType && (!('max' in propType) || Number.isFinite(propType.max)) && (!('min' in propType) || Number.isFinite(propType.min));
    },
    validate: function validate(value, propType) {
      return Number.isFinite(value) && (!('max' in propType) || value <= propType.max) && (!('min' in propType) || value >= propType.min);
    }
  }
};

export function parsePropTypes(propDefs) {
  var propTypes = {};
  var defaultProps = {};
  var _iteratorNormalCompletion = true;
  var _didIteratorError = false;
  var _iteratorError = undefined;

  try {
    for (var _iterator = Object.entries(propDefs)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
      var _step$value = _slicedToArray(_step.value, 2),
          propName = _step$value[0],
          propDef = _step$value[1];

      var propType = parsePropType(propName, propDef);
      propTypes[propName] = propType;
      defaultProps[propName] = propType.value;
    }
  } catch (err) {
    _didIteratorError = true;
    _iteratorError = err;
  } finally {
    try {
      if (!_iteratorNormalCompletion && _iterator.return) {
        _iterator.return();
      }
    } finally {
      if (_didIteratorError) {
        throw _iteratorError;
      }
    }
  }

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

// Parses one property definition entry. Either contains:
// * a valid prop type object ({type, ...})
// * or just a default value, in which case type and name inference is used
function parsePropType(name, propDef) {
  switch (getTypeOf(propDef)) {
    case 'object':
      propDef = normalizePropDefinition(name, propDef);
      return parsePropDefinition(propDef);

    case 'array':
      return guessArrayType(name, propDef);

    case 'boolean':
      return { name: name, type: 'boolean', value: propDef };

    case 'number':
      return guessNumberType(name, propDef);

    case 'function':
      return { name: name, type: 'function', value: propDef };
    // return guessFunctionType(name, propDef);

    default:
      return { name: name, type: 'unknown', value: propDef };
  }
}

function guessArrayType(name, array) {
  if (/color/i.test(name) && (array.length === 3 || array.length === 4)) {
    return { name: name, type: 'color', value: array };
  }
  return { name: name, type: 'array', value: array };
}

function normalizePropDefinition(name, propDef) {
  if (!('type' in propDef)) {
    if (!('value' in propDef)) {
      // If no type and value this object is likely the value
      return { name: name, type: 'object', value: propDef };
    }
    return Object.assign({ name: name, type: getTypeOf(propDef.value) }, propDef);
  }
  return Object.assign({ name: name }, propDef);
}

function parsePropDefinition(propDef) {
  var type = propDef.type;

  var typeDefinition = TYPE_DEFINITIONS[type] || {};
  var typeValidator = typeDefinition.typeValidator;

  if (typeValidator) {
    assert(typeValidator(propDef), 'Illegal prop type');
  }

  return propDef;
}

function guessNumberType(name, value) {
  var isKnownProp = /radius|scale|width|height|pixel|size|miter/i.test(name) && /^((?!scale).)*$/.test(name);
  var max = isKnownProp ? 100 : 1;
  var min = 0;
  return {
    name: name,
    type: 'number',
    max: Math.max(value, max),
    min: Math.min(value, min),
    value: value
  };
}

// improved version of javascript typeof that can distinguish arrays and null values
function getTypeOf(value) {
  if (Array.isArray(value) || ArrayBuffer.isView(value)) {
    return 'array';
  }
  if (value === null) {
    return 'null';
  }
  return typeof value === 'undefined' ? 'undefined' : _typeof(value);
}
//# sourceMappingURL=prop-types.js.map