import React from 'react';
import { reject } from 'rambda';

const computeBoxStyle = (
  {
    // Maybe rhythm props.
    margin,
    marginVertical = margin,
    marginHorizontal = margin,
    marginTop = marginVertical,
    marginBottom = marginVertical,
    marginLeft = marginHorizontal,
    marginRight = marginHorizontal,
    padding,
    paddingVertical = padding,
    paddingHorizontal = padding,
    paddingTop = paddingVertical,
    paddingBottom = paddingVertical,
    paddingLeft = paddingHorizontal,
    paddingRight = paddingHorizontal,
    height,
    maxHeight,
    maxWidth,
    minHeight,
    minWidth,
    width,
    bottom,
    left,
    right,
    top,

    flex,
    backgroundColor,
    color,
    cursor,
    textAlign,
    fontSize,

    // Border props.
    borderColor,
    // We can't use borderColor as default because some component in React Native,
    // for example Image, doesn't support that.
    borderBottomColor,
    borderLeftColor,
    borderRightColor,
    borderTopColor,
    borderRadius,
    borderBottomLeftRadius = borderRadius,
    borderBottomRightRadius = borderRadius,
    borderTopLeftRadius = borderRadius,
    borderTopRightRadius = borderRadius,
    borderWidth,
    borderBottomWidth = borderWidth,
    borderLeftWidth = borderWidth,
    borderRightWidth = borderWidth,
    borderTopWidth = borderWidth,
    borderStyle,
    boxShadow,

    // Just value props.
    alignContent,
    alignItems,
    alignSelf,
    flexBasis,
    flexDirection,
    flexGrow,
    flexShrink,
    flexWrap,
    justifyContent,
    opacity,
    overflow,
    overflowX,
    overflowY,
    pointerEvents,
    position,
    textOverflow,
    whiteSpace,
    zIndex,

    ...props
  },
) => {
  let style = {
    position: 'relative',
    flexDirection: 'column',
    display: 'flex',
  };

  if (typeof flex === 'number') {
    style.flexBasis = 'auto';
    style.flexGrow = flex;
    style.flexShrink = 1;
  }

  const justValueProps = {
    margin,
    marginVertical,
    marginHorizontal,
    marginTop,
    marginBottom,
    marginLeft,
    marginRight,
    padding,
    paddingVertical,
    paddingHorizontal,
    paddingTop,
    paddingBottom,
    paddingLeft,
    paddingRight,
    height,
    maxHeight,
    maxWidth,
    minHeight,
    minWidth,
    width,
    bottom,
    left,
    right,
    top,

    flex,
    backgroundColor,
    color,
    cursor,
    textAlign,
    fontSize,

    // Border props.
    borderColor,
    // We can't use borderColor as default because some component in React Native,
    // for example Image, doesn't support that.
    borderBottomColor,
    borderLeftColor,
    borderRightColor,
    borderTopColor,
    borderRadius,
    borderBottomLeftRadius,
    borderBottomRightRadius,
    borderTopLeftRadius,
    borderTopRightRadius,
    borderWidth,
    borderBottomWidth,
    borderLeftWidth,
    borderRightWidth,
    borderTopWidth,
    borderStyle,
    boxShadow,

    // Just value props.
    alignContent,
    alignItems,
    alignSelf,
    flexBasis,
    flexDirection,
    flexGrow,
    flexShrink,
    flexWrap,
    justifyContent,
    opacity,
    overflow,
    overflowX,
    overflowY,
    pointerEvents,
    position,
    textOverflow,
    whiteSpace,
    zIndex,
  };

  Object.keys(justValueProps)
    .filter(prop => {
      const value = justValueProps[prop];
      const isDefined = typeof value === 'number' || value;
      return isDefined;
    })
    .forEach(prop => {
      const value = justValueProps[prop];
      style[prop] = value;
    });

  return [style, props];
};

class Box extends React.PureComponent {
  render() {
    const {
      as = 'div',
      className,
      style,
      nativeRef,
      ...props
    } = this.props;

    const [boxStyle, restProps] = computeBoxStyle(props);

    let combinedStyles = {
      ...boxStyle,
      ...style,
    };

    combinedStyles = reject(val => Number.isNaN(val), combinedStyles);

    const styles = {
      style: combinedStyles,
      className
    };

    return React.createElement(as, { ...restProps, ...styles, ref: nativeRef });
  }
}

export default Box;