import { React, PropTypes, classnames } from '@gravityforms/libraries';
import { spacerClasses } from '@gravityforms/utils';
import Card from '../Card';
import Box from '../../../elements/Box';
import Heading from '../../../elements/Heading';
import Icon from '../../../elements/Icon';
import Text from '../../../elements/Text';

const { forwardRef } = React;

/**
 * @module MetricCard
 * @description The metric card component. used to display icons with a measurement of some kind.
 *
 * @since 4.4.4
 *
 * @param {object}                    props                   Component props.
 * @param {JSX.Element|null}          props.children          React element children.
 * @param {JSX.Element|number|string} props.count             The count to display.
 * @param {object}                    props.contentAttributes Custom attributes for the content box.
 * @param {string|Array|object}       props.contentClasses    Custom classes for the content box.
 * @param {object}                    props.countAttributes   Custom attributes for the count text.
 * @param {string|Array|object}       props.countClasses      Custom classes for the count text.
 * @param {object}                    props.customAttributes  Custom attributes for the component.
 * @param {JSX.Element|null}          props.customIcon        React element for a custom icon.
 * @param {string|Array|object}       props.customClasses     Custom classes for the component.
 * @param {object}                    props.iconAttributes    Custom attributes for the icon.
 * @param {boolean}                   props.hasIcon           Whether to include the icon.
 * @param {number}                    props.spacing           Spacing around the card.
 * @param {string}                    props.title             The title to display.
 * @param {object}                    props.titleAttributes   Custom attributes for the title.
 * @param {string|Array|object}       props.titleClasses      Custom classes for the title.
 * @param {string}                    props.type              The type of metric card.
 * @param {object|null}               ref                     Ref to the component.
 *
 * @return {JSX.Element} The metric card component.
 *
 * @example
 * import MetricCard from '@gravityforms/components/react/admin/modules/Cards/MetricCard';
 *
 * return (
 *     <MetricCard
 *         style="metric"
 *     />
 * );
 *
 */
const MetricCard = forwardRef( ( {
	children = null,
	count = 0,
	contentAttributes = {},
	contentClasses = [],
	countAttributes = {},
	countClasses = [],
	customAttributes = {},
	customClasses = [],
	customIcon = null,
	iconAttributes = {},
	hasIcon = true,
	spacing = 0,
	title = '',
	titleAttributes = {},
	titleClasses = [],
	type = 'info',
}, ref ) => {
	const componentProps = {
		customClasses: classnames( {
			'gform-card--metric': true,
			[ `gform-card--metric-${ type }` ]: true,
			...spacerClasses( spacing ),
		}, customClasses ),
		...customAttributes,
		baseClass: false,
		ref,
	};

	const iconProps = {
		preset: `metric-${ type }`,
		...iconAttributes,
	};

	const contentProps = {
		customClasses: classnames( {
			'gform-card__metric-content': true,
		}, contentClasses ),
		spacing: [ 0, 0, 0, 6 ],
		...contentAttributes,
	};

	const titleProps = {
		customClasses: classnames( {
			'gform-card__metric-title': true,
		}, titleClasses ),
		size: 'text-sm',
		spacing: [ 0, 0, 1, 0 ],
		weight: 'medium',
		tagName: 'h3',
		...titleAttributes,
	};

	const countProps = {
		customClasses: classnames( {
			'gform-card__metric-count': true,
		}, countClasses ),
		size: 'text-xl',
		weight: 'semibold',
		...countAttributes,
	};

	return (
		<Card { ...componentProps }>
			{ hasIcon && ( customIcon || <Icon { ...iconProps } /> ) }
			<Box { ...contentProps }>
				<Heading { ...titleProps }>{ title }</Heading>
				<Text { ...countProps }>{ count }</Text>
			</Box>
			{ children }
		</Card>
	);
} );

MetricCard.propTypes = {
	children: PropTypes.node,
	count: PropTypes.oneOfType( [
		PropTypes.element,
		PropTypes.number,
		PropTypes.string,
	] ),
	contentAttributes: PropTypes.object,
	contentClasses: PropTypes.oneOfType( [
		PropTypes.array,
		PropTypes.object,
		PropTypes.string,
	] ),
	countAttributes: PropTypes.object,
	countClasses: PropTypes.oneOfType( [
		PropTypes.array,
		PropTypes.object,
		PropTypes.string,
	] ),
	customAttributes: PropTypes.object,
	customClasses: PropTypes.oneOfType( [
		PropTypes.array,
		PropTypes.object,
		PropTypes.string,
	] ),
	iconAttributes: PropTypes.object,
	hasIcon: PropTypes.bool,
	title: PropTypes.string,
	titleAttributes: PropTypes.object,
	titleClasses: PropTypes.oneOfType( [
		PropTypes.array,
		PropTypes.object,
		PropTypes.string,
	] ),
	type: PropTypes.oneOf( [ 'info', 'success', 'warn', 'error' ] ),
};

MetricCard.displayName = 'Cards/MetricCard';

export default MetricCard;
