import { React, classnames, PropTypes } from '@gravityforms/libraries';
import { spacerClasses } from '@gravityforms/utils';

const { forwardRef } = React;

/**
 * @module Box
 * @description Renders a simple box component for containing width or height.
 *
 * @since 1.1.15
 *
 * @param {object}                     props                  Component props.
 * @param {JSX.Element}                props.children         React element children.
 * @param {object}                     props.customAttributes Custom attributes for the component.
 * @param {string|Array|object}        props.customClasses    Custom classes for the component.
 * @param {string}                     props.display          The display property for the box.
 * @param {boolean}                    props.setDisplay       Whether to set the display property for the box.
 * @param {string|number|Array|object} props.spacing          The spacing for the component, as a string, number, array, or object.
 * @param {string}                     props.tagName          The tagname for the box, defaults to `div`.
 * @param {string}                     props.unit             The css units for the x and y props.
 * @param {number}                     props.x                The width property.
 * @param {string}                     props.xProp            The css property in react style syntax for the width, defaults to maxWidth.
 * @param {number}                     props.y                The height property.
 * @param {string}                     props.yProp            The css property in react style syntax for the height, defaults to minHeight.
 * @param {object|null}                ref                    Ref to the component.
 *
 * @return {JSX.Element} The box component.
 *
 * @example
 * import Box from '@gravityforms/components/react/admin/elements/Box';
 *
 * return (
 *     <Box tagName="span">
 *         { 'children' }
 *     </Box>
 * );
 *
 */
const Box = forwardRef( ( {
	children = null,
	customAttributes = {},
	customClasses = [],
	display = 'block',
	setDisplay = true,
	spacing = '',
	tagName = 'div',
	unit = 'px',
	x = 0,
	xProp = 'maxWidth',
	y = 0,
	yProp = 'minHeight',
}, ref ) => {
	const style = {};
	if ( setDisplay ) {
		style.display = display;
	}
	if ( x ) {
		style[ xProp ] = `${ x }${ unit }`;
	}
	if ( y ) {
		style[ yProp ] = `${ y }${ unit }`;
	}
	const mergedStyles = { ...style, ...( customAttributes.style || {} ) };

	const boxProps = {
		className: classnames( {
			'gform-box': true,
			...spacerClasses( spacing ),
		}, customClasses ),
		ref,
		...customAttributes,
		style: mergedStyles,
	};

	const Container = tagName;

	return <Container { ...boxProps }>{ children }</Container>;
} );

Box.propTypes = {
	children: PropTypes.oneOfType( [
		PropTypes.arrayOf( PropTypes.node ),
		PropTypes.node,
	] ),
	customAttributes: PropTypes.object,
	customClasses: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.array,
		PropTypes.object,
	] ),
	display: PropTypes.string,
	setDisplay: PropTypes.bool,
	spacing: PropTypes.oneOfType( [
		PropTypes.string,
		PropTypes.number,
		PropTypes.array,
		PropTypes.object,
	] ),
	tagName: PropTypes.string,
	unit: PropTypes.string,
	x: PropTypes.number,
	xProp: PropTypes.string,
	y: PropTypes.number,
	yProp: PropTypes.string,
};

Box.displayName = 'Box';

export default Box;
