"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

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

var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _texture = require("../utils/texture");

var _deepEqual = require("../utils/deep-equal");

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

var TYPE_DEFINITIONS = {
  boolean: {
    validate: function validate(value, propType) {
      return true;
    },
    equal: function equal(value1, value2, propType) {
      return Boolean(value1) === Boolean(value2);
    }
  },
  number: {
    validate: function validate(value, propType) {
      return Number.isFinite(value) && (!('max' in propType) || value <= propType.max) && (!('min' in propType) || value >= propType.min);
    }
  },
  color: {
    validate: function validate(value, propType) {
      return propType.optional && !value || isArray(value) && (value.length === 3 || value.length === 4);
    },
    equal: function equal(value1, value2, propType) {
      return (0, _deepEqual.deepEqual)(value1, value2, 1);
    }
  },
  accessor: {
    validate: function validate(value, propType) {
      var valueType = getTypeOf(value);
      return valueType === 'function' || valueType === getTypeOf(propType.value);
    },
    equal: function equal(value1, value2, propType) {
      if (typeof value2 === 'function') {
        return true;
      }

      return (0, _deepEqual.deepEqual)(value1, value2, 1);
    }
  },
  array: {
    validate: function validate(value, propType) {
      return propType.optional && !value || isArray(value);
    },
    equal: function equal(value1, value2, propType) {
      var compare = propType.compare;
      var depth = Number.isInteger(compare) ? compare : compare ? 1 : 0;
      return compare ? (0, _deepEqual.deepEqual)(value1, value2, depth) : value1 === value2;
    }
  },
  object: {
    equal: function equal(value1, value2, propType) {
      if (propType.ignore) {
        return true;
      }

      var compare = propType.compare;
      var depth = Number.isInteger(compare) ? compare : compare ? 1 : 0;
      return compare ? (0, _deepEqual.deepEqual)(value1, value2, depth) : value1 === value2;
    }
  },
  function: {
    validate: function validate(value, propType) {
      return propType.optional && !value || typeof value === 'function';
    },
    equal: function equal(value1, value2, propType) {
      var shouldIgnore = !propType.compare && propType.ignore !== false;
      return shouldIgnore || value1 === value2;
    }
  },
  data: {
    transform: function transform(value, propType, component) {
      var dataTransform = component.props.dataTransform;
      return dataTransform && value ? dataTransform(value) : value;
    }
  },
  image: {
    transform: function transform(value, propType, component) {
      var context = component.context;

      if (!context || !context.device) {
        return null;
      }

      return (0, _texture.createTexture)(component.id, context.device, value, _objectSpread(_objectSpread({}, propType.parameters), component.props.textureParameters));
    },
    release: function release(value, propType, component) {
      (0, _texture.destroyTexture)(component.id, value);
    }
  }
};

function parsePropTypes(propDefs) {
  var propTypes = {};
  var defaultProps = {};
  var deprecatedProps = {};

  for (var _i = 0, _Object$entries = Object.entries(propDefs); _i < _Object$entries.length; _i++) {
    var _Object$entries$_i = (0, _slicedToArray2.default)(_Object$entries[_i], 2),
        _propName = _Object$entries$_i[0],
        propDef = _Object$entries$_i[1];

    var deprecated = propDef === null || propDef === void 0 ? void 0 : propDef.deprecatedFor;

    if (deprecated) {
      deprecatedProps[_propName] = Array.isArray(deprecated) ? deprecated : [deprecated];
    } else {
      var _propType = parsePropType(_propName, propDef);

      propTypes[_propName] = _propType;
      defaultProps[_propName] = _propType.value;
    }
  }

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

function parsePropType(name, propDef) {
  switch (getTypeOf(propDef)) {
    case 'object':
      return normalizePropDefinition(name, propDef);

    case 'array':
      return normalizePropDefinition(name, {
        type: 'array',
        value: propDef,
        compare: false
      });

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

    case 'number':
      return normalizePropDefinition(name, {
        type: 'number',
        value: propDef
      });

    case 'function':
      return normalizePropDefinition(name, {
        type: 'function',
        value: propDef,
        compare: true
      });

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

function normalizePropDefinition(name, propDef) {
  if (!('type' in propDef)) {
    if (!('value' in propDef)) {
      return {
        name: name,
        type: 'object',
        value: propDef
      };
    }

    return _objectSpread({
      name: name,
      type: getTypeOf(propDef.value)
    }, propDef);
  }

  return _objectSpread(_objectSpread({
    name: name
  }, TYPE_DEFINITIONS[propDef.type]), propDef);
}

function isArray(value) {
  return Array.isArray(value) || ArrayBuffer.isView(value);
}

function getTypeOf(value) {
  if (isArray(value)) {
    return 'array';
  }

  if (value === null) {
    return 'null';
  }

  return (0, _typeof2.default)(value);
}
//# sourceMappingURL=prop-types.js.map