'use strict';

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

var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');

var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

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

var _propTypes2 = _interopRequireDefault(_propTypes);

var _recompose = require('recompose');

var _reactRouterDom = require('react-router-dom');

var _userSpacing = require('../../extensions/userSpacing');

var _userSpacing2 = _interopRequireDefault(_userSpacing);

var _ExternalContentAnchor = require('./styles/ExternalContentAnchor');

var _ExternalContentAnchor2 = _interopRequireDefault(_ExternalContentAnchor);

var _ExternalIconAnchor = require('./styles/ExternalIconAnchor');

var _ExternalIconAnchor2 = _interopRequireDefault(_ExternalIconAnchor);

var _ExternalTextAnchor = require('./styles/ExternalTextAnchor');

var _ExternalTextAnchor2 = _interopRequireDefault(_ExternalTextAnchor);

var _InternalContentAnchor = require('./styles/InternalContentAnchor');

var _InternalContentAnchor2 = _interopRequireDefault(_InternalContentAnchor);

var _InternalTextAnchor = require('./styles/InternalTextAnchor');

var _InternalTextAnchor2 = _interopRequireDefault(_InternalTextAnchor);

var _InternalIconAnchor = require('./styles/InternalIconAnchor');

var _InternalIconAnchor2 = _interopRequireDefault(_InternalIconAnchor);

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

var inferType = function inferType(children) {
  if (children === null) {
    return 'wrap';
  }

  if (children.type && children.type.displayName === 'Icon') {
    return 'icon';
  }

  if (typeof children === 'string') {
    return 'text';
  }

  return 'wrap';
};
// 'internal' anchors link to in-app pages, not external URLs


var matchReactRouter = function matchReactRouter(to, match, exact) {
  var active = void 0;
  if (!exact) {
    // use the default behavior for non-exact matches
    active = !!match;
  } else {
    // when we expect an exact match, dont allow react-router null
    // value, additionally verify special chars are used
    active = match == null ? false : match.url === to;
  }
  return active;
};

var Anchor = function (_React$Component) {
  (0, _inherits3.default)(Anchor, _React$Component);

  function Anchor() {
    var _ref;

    var _temp, _this, _ret;

    (0, _classCallCheck3.default)(this, Anchor);

    for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = Anchor.__proto__ || (0, _getPrototypeOf2.default)(Anchor)).call.apply(_ref, [this].concat(args))), _this), _this.isExternal = function () {
      var _this$props = _this.props,
          external = _this$props.external,
          to = _this$props.to;

      if (external !== undefined) {
        return external;
      }
      return (/^(https?:)*\/\//.test(to)
      );
    }, _this.getComponentType = function () {
      var _this$props2 = _this.props,
          type = _this$props2.type,
          external = _this$props2.external,
          children = _this$props2.children,
          to = _this$props2.to,
          icon = _this$props2.icon,
          ExternalTextAnchor = _this$props2.ExternalTextAnchor,
          ExternalIconAnchor = _this$props2.ExternalIconAnchor,
          ExternalContentAnchor = _this$props2.ExternalContentAnchor,
          InternalTextAnchor = _this$props2.InternalTextAnchor,
          InternalIconAnchor = _this$props2.InternalIconAnchor,
          InternalContentAnchor = _this$props2.InternalContentAnchor;

      var finalType = type || (!!icon ? 'icon' : inferType(children));
      var finalExternal = _this.isExternal();
      switch (finalType) {
        case 'wrap':
        case 'content':
          return finalExternal ? ExternalContentAnchor : InternalContentAnchor;
        case 'icon':
          return finalExternal ? ExternalIconAnchor : InternalIconAnchor;
        default:
          return finalExternal ? ExternalTextAnchor : InternalTextAnchor;
      }
    }, _this.handleClick = function (event) {
      var _this$props3 = _this.props,
          onClick = _this$props3.onClick,
          to = _this$props3.to,
          disabled = _this$props3.disabled;

      // Don't handle navigation if disabled

      if (disabled) return event.preventDefault();

      // if the user isn't using this link to navigate,
      // prevent default navigation
      if (onClick && to === '#') {
        event.preventDefault();
        onClick(event);
      } else if (onClick) {
        // still do onClick event if navigation occurs
        onClick(event);
      }
    }, _this.childrenWithProps = function (extraProps) {
      var children = _this.props.children;

      if (!children) {
        return null;
      }
      if (typeof children === 'string') {
        return children;
      }
      return _react2.default.Children.map(children, function (child) {
        if (typeof child === 'string') {
          return child;
        }
        return _react2.default.cloneElement(child, extraProps);
      });
    }, _this.extraProps = function () {
      var _this$props4 = _this.props,
          to = _this$props4.to,
          newTab = _this$props4.newTab,
          disabled = _this$props4.disabled;

      var newTabProps = newTab && !disabled ? { rel: 'noopener', target: '_blank' } : {};
      if (_this.isExternal() && !disabled) {
        return (0, _extends3.default)({
          href: to
        }, newTabProps);
      } else {
        return (0, _extends3.default)({
          to: to
        }, newTabProps);
      }
    }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
  }

  // provides extra properties based on certain factors to the underlying element


  (0, _createClass3.default)(Anchor, [{
    key: 'render',
    value: function render() {
      var _this2 = this;

      var _props = this.props,
          to = _props.to,
          exact = _props.exact,
          children = _props.children,
          active = _props.active,
          rest = (0, _objectWithoutProperties3.default)(_props, ['to', 'exact', 'children', 'active']);


      var Component = this.getComponentType();

      return _react2.default.createElement(_reactRouterDom.Route, {
        path: to,
        exact: exact,
        children: function children(_ref2) {
          var match = _ref2.match;
          return _react2.default.createElement(
            Component,
            (0, _extends3.default)({}, _this2.extraProps(), {
              onClick: _this2.handleClick,
              spacing: _userSpacing2.default.text(_this2.props)
            }, rest),
            _this2.childrenWithProps({
              active: typeof active === 'function' ? active(to, match, exact) : !!active
            })
          );
        }
      });
    }
  }]);
  return Anchor;
}(_react2.default.Component);

Anchor.propTypes = {
  /**
   * A location to link to with this anchor.
   */
  to: _propTypes2.default.string,
  /**
   * Rendered contents inside the anchor.
   */
  children: _propTypes2.default.node,
  /**
   * Anchors pass an 'active' prop to their children when the route matches. This controls whether that is exact matching.
   */
  exact: _propTypes2.default.bool,
  /**
   * A handler for the anchor's onclick event.
   */
  onClick: _propTypes2.default.func,
  /**
   * Bind a handler for the mouseEnter event
   */
  onMouseEnter: _propTypes2.default.func,
  /**
   * Bind a handler for the mouseLeave event
   */
  onMouseLeave: _propTypes2.default.func,
  /**
   * whether the contents should be treated as text (underlined),
   * icon (has specific styling), or 'content' (no styling).
   */
  type: _propTypes2.default.oneOf(['text', 'icon', 'wrap', 'content']),
  /**
   * Use to override the automatic inference of whether the URL is external or internal
   */
  external: _propTypes2.default.bool,
  /**
   * A class name to pass to the <a> element.
   */
  className: _propTypes2.default.string,
  /**
   * An id to pass to the <a> element.
   */
  id: _propTypes2.default.string,
  /**
   * Opens the link in a new tab.
   */
  newTab: _propTypes2.default.bool,
  /**
   * Adds an icon to the beginning of the link and changes the styling to "icon" mode
   */
  icon: _propTypes2.default.string,
  /**
   * This prop can be used to 'pseudo-focus' an anchor visually. Useful when
   * supporting some advanced keyboard navigation scenarios.
   */
  appearFocused: _propTypes2.default.bool,
  /**
   * If set to true, disables the Anchor.  While disabled, the Anchor will neither react to mouseover events
   * nor will it react to onclick events.
   */
  disabled: _propTypes2.default.bool,
  /**
   * Specify a CSS value or an object { top, right, bottom, left } or { vertical, horizontal } to
   * control the spacing around the heading. Defaults to a large space below the element.
   */
  spacing: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.object]),
  /**
   * Renders a text anchor linking to an external site
   */
  ExternalTextAnchor: _propTypes2.default.func,
  /**
   * Renders an icon anchor linking to an external site
   */
  ExternalIconAnchor: _propTypes2.default.func,
  /**
   * Renders a content (image, element) anchor linking to an external site
   */
  ExternalContentAnchor: _propTypes2.default.func,
  /**
   * Renders a text anchor linking to a page in-app
   */
  InternalTextAnchor: _propTypes2.default.func,
  /**
   * Renders an icon anchor linking to a page in-app
   */
  InternalIconAnchor: _propTypes2.default.func,
  /**
   * Renders a content (image, element) anchor linking to a page in-app
   */
  InternalContentAnchor: _propTypes2.default.func,
  /**
   * Resolves whether a link is active. Specifying custom rules for whether
   * a link is active may be necessary when using custom onClick logic
   */
  active: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.bool])
};
Anchor.defaultProps = {
  to: '#',
  children: null,
  exact: false,
  onClick: function onClick() {
    return null;
  },
  type: null,
  className: null,
  id: null,
  newTab: false,
  appearFocused: false,
  external: undefined,
  disabled: false,
  spacing: { horizontal: 'auto' },
  ExternalTextAnchor: _ExternalTextAnchor2.default,
  ExternalIconAnchor: _ExternalIconAnchor2.default,
  ExternalContentAnchor: _ExternalContentAnchor2.default,
  InternalTextAnchor: _InternalTextAnchor2.default,
  InternalIconAnchor: _InternalIconAnchor2.default,
  InternalContentAnchor: _InternalContentAnchor2.default,
  active: matchReactRouter
};


Anchor.Danger = Anchor.Negative = (0, _recompose.defaultProps)({
  ExternalTextAnchor: _ExternalTextAnchor2.default.Danger,
  ExternalIconAnchor: _ExternalIconAnchor2.default.Danger,
  InternalTextAnchor: _InternalTextAnchor2.default.Danger,
  InternalIconAnchor: _InternalIconAnchor2.default.Danger
})(Anchor);

Anchor.Positive = (0, _recompose.defaultProps)({
  ExternalTextAnchor: _ExternalTextAnchor2.default.Positive,
  ExternalIconAnchor: _ExternalIconAnchor2.default.Positive,
  InternalTextAnchor: _InternalTextAnchor2.default.Positive,
  InternalIconAnchor: _InternalIconAnchor2.default.Positive
})(Anchor);

Anchor.Dark = (0, _recompose.defaultProps)({
  ExternalTextAnchor: _ExternalTextAnchor2.default.Dark,
  ExternalIconAnchor: _ExternalIconAnchor2.default.Dark,
  InternalTextAnchor: _InternalTextAnchor2.default.Dark,
  InternalIconAnchor: _InternalIconAnchor2.default.Dark
})(Anchor);

Anchor.Inverted = (0, _recompose.defaultProps)({
  ExternalTextAnchor: _ExternalTextAnchor2.default.Inverted,
  ExternalIconAnchor: _ExternalIconAnchor2.default.Inverted,
  InternalTextAnchor: _InternalTextAnchor2.default.Inverted,
  InternalIconAnchor: _InternalIconAnchor2.default.Inverted
})(Anchor);

exports.default = Anchor;