'use strict';

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

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _themeGet = require('./themeGet');

var _themeGet2 = _interopRequireDefault(_themeGet);

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

/**
 * EXPERIMENTAL
 *
 * Takes a user's `spacing` prop and converts it into margins
 * which can be applied to text elements so that they are spaced
 * from the cap-line and baseline, rather than the element bounds.
 *
 * This is accomplished by calculating margin with offsets of
 * em values to 'dig' into the element a bit to reach the cap and baselines.
 * These em values are based on visual inspection and would vary
 * by font.
 *
 * Passing props as a whole so that we have access to dynamic theme
 * information.
 */

var getSize = function getSize(value, props) {
  switch (('' + value).toLowerCase()) {
    case 'xs':
    case 'extraSmall':
      return (0, _themeGet2.default)('spacing.extraSmall')(props);
    case 'sm':
    case 'small':
      return (0, _themeGet2.default)('spacing.small')(props);
    case 'md':
    case 'medium':
      return (0, _themeGet2.default)('spacing.medium')(props);
    case 'lg':
    case 'large':
      return (0, _themeGet2.default)('spacing.large')(props);
    case 'xl':
    case 'extraLarge':
      return (0, _themeGet2.default)('spacing.extraLarge')(props);
    default:
      // if it's a unit string, return it
      if (isNaN(parseInt('' + value, 10))) {
        return value;
      }
      // if the user supplied a number, assume pixels
      return parseInt('' + value, 10) + 'px';
  }
};

var calcTopOffset = exports.calcTopOffset = function calcTopOffset(lineHeight) {
  return lineHeight / -5.25 * (lineHeight / 1.5) + 'em';
};
var calcBottomOffset = exports.calcBottomOffset = function calcBottomOffset(lineHeight) {
  return lineHeight / -3.5 * (lineHeight / 1.5) + 'em';
};

var userTextSpacingWithLineHeight = function userTextSpacingWithLineHeight(lineHeight) {
  return function (props) {
    var spacing = props.spacing;

    /* these offset values collapse the outer element boundaries so that
     * adjacent layout aligns with the cap and baseline of the text inside.
     *
     * This logic is a little fuzzy. Offsets of -0.25em and -0.5em work
     * perfectly for a line height of 1.5, but they start to drift as it gets
     * smaller or larger, so we further scale the value based on its difference
     * from 1.5. Experiments suggest this produces reasonably accurate results.
     */

    var topOffset = calcTopOffset(lineHeight);
    var bottomOffset = calcBottomOffset(lineHeight);

    if (!spacing) {
      // this is default 'no spacing', will align adjacent elements
      // to the cap and baseline directly
      return topOffset + ' 0 ' + bottomOffset + ' 0';
    }

    if (_lodash2.default.isPlainObject(spacing)) {
      var top = _lodash2.default.get(spacing, 'top', _lodash2.default.get(spacing, 'vertical', '0px'));
      var right = _lodash2.default.get(spacing, 'right', _lodash2.default.get(spacing, 'horizontal', '0px'));
      var bottom = _lodash2.default.get(spacing, 'bottom', _lodash2.default.get(spacing, 'vertical', '0px'));
      var left = _lodash2.default.get(spacing, 'left', _lodash2.default.get(spacing, 'horizontal', '0px'));

      return 'calc(' + topOffset + ' + ' + getSize(top, props) + ') ' + getSize(right, props) + ' calc(' + bottomOffset + ' + ' + getSize(bottom, props) + ') ' + getSize(left, props);
    } else if (_lodash2.default.isString(spacing)) {
      var size = getSize(spacing, props);
      return 'calc(' + topOffset + ' + ' + size + ') ' + size + ' calc(' + bottomOffset + ' + ' + size + ') ' + size;
    }

    throw new Error('Invalid spacing prop value ' + spacing + ', must be a single CSS value string or object { top, right, bottom, left }');
  };
};

var userSpacing = userTextSpacingWithLineHeight(0);
// the default global line height for text is 1.5
userSpacing.text = userTextSpacingWithLineHeight(1.5);
userSpacing.text.withLineHeight = userTextSpacingWithLineHeight;
// allow static access to power functions
userSpacing.withLineHeight = userTextSpacingWithLineHeight;

exports.default = userSpacing;