import { React, PropTypes, classnames } from '@gravityforms/libraries';
import Card from '../Card';
import Image from '../../../elements/Image';
import Button from '../../../elements/Button';
import Link from '../../../elements/Link';
import Tag from '../../../elements/Tag';
import Box from '../../../elements/Box';
import Heading from '../../../elements/Heading';
import Text from '../../../elements/Text';

const { forwardRef } = React;

/**
 * @module FormTemplateCard
 * @description The form template card component.
 *
 * @since 1.1.15
 *
 * @param {object}              props                       Component props.
 * @param {string}              props.bgColor               The background color of the card.
 * @param {object}              props.blankButtonAttributes The attributes for the blank button.
 * @param {object}              props.bottomBoxAttributes   Custom attributes for the bottom box component.
 * @param {JSX.Element|null}    props.bottomChildren        React elements for the bottom container.
 * @param {object}              props.customAttributes      Custom attributes for the component.
 * @param {string|Array|object} props.customClasses         Custom classes for the component.
 * @param {object}              props.headingAttributes     Custom attributes for the card heading component.
 * @param {object}              props.imageAttributes       Custom attributes for the card image component.
 * @param {object}              props.primaryCtaAttrs       Custom attributes for the primary CTA.
 * @param {object}              props.secondaryCtaAttrs     Custom attributes for the secondary CTA.
 * @param {string}              props.style                 The style of the form template card.
 * @param {object}              props.tagAttributes         Custom attributes for the tag component.
 * @param {object}              props.textAttributes        Custom attributes for the card text component.
 * @param {object}              props.topBoxAttributes      Custom attributes for the top box component.
 * @param {JSX.Element|null}    props.topChildren           React elements for the top container.
 * @param {object|null}         ref                         Ref to the component.
 *
 * @return {JSX.Element} The form template card component.
 *
 * @example
 * import FormTemplateCard from '@gravityforms/components/react/admin/modules/Cards/FormTemplateCard';
 *
 * return (
 *     <FormTemplateCard
 *         bgColor="iceberg-blue"
 *         headingAttributes={{
 *             content: 'Card title',
 *             weight: 'medium',
 *             size: 'text-sm',
 *             tagName: 'h2',
 *         }}
 *         style="form-template"
 *     />
 * );
 *
 */
const FormTemplateCard = forwardRef( ( {
	bgColor = '',
	blankButtonAttributes = {},
	bottomBoxAttributes = {},
	bottomChildren = null,
	customAttributes = {},
	customClasses = [],
	headingAttributes = {},
	imageAttributes = {},
	primaryCtaAttrs = {},
	secondaryCtaAttrs = {},
	style = '',
	tagAttributes = {},
	textAttributes = {},
	topBoxAttributes = {},
	topChildren = null,
}, ref ) => {
	const getImage = () => {
		const imageAttrs = {
			...imageAttributes,
			customClasses: [
				'gform-card__image',
				...( imageAttributes.customClasses || [] ),
			],
		};

		return <Image { ...imageAttrs } />;
	};

	const getBlankIcon = () => {
		return (
			<span className="gform-button gform-button--size-height-xl gform-button--white">
				<span className="gform-icon gform-icon--plus-regular gform-button__icon"></span>
			</span>
		);
	};

	const getCta = ( ctaAttrs, position ) => {
		const ctaProps = {
			...ctaAttrs,
			customClasses: classnames( {
				[ `gform-card__form-template-${ position }-button` ]: true,
				'gform-button': true,
				'gform-button--size-xs': true,
				'gform-button--width-auto': true,
				'gform-button--white': position === 'secondary',
			} ),
			size: 'size-xs',
		};

		if ( position === 'primary' ) {
			ctaProps.type = 'primary-new';
		}

		if ( ctaProps.ctaType === 'button' ) {
			return <Button { ...ctaProps } />;
		}

		if ( ctaProps.ctaType === 'link' ) {
			return <Link { ...ctaProps } />;
		}
	};

	const getImageBoxHover = () => {
		return (
			<div className={ 'gform-card__form-template-hover-buttons' }>
				<div className={ 'gform-card__form-template-buttons-container' }>
					{
						primaryCtaAttrs &&
						Object.keys( primaryCtaAttrs ).length &&
						getCta( primaryCtaAttrs, 'primary' )
					}
					{
						secondaryCtaAttrs &&
						Object.keys( secondaryCtaAttrs ).length &&
						getCta( secondaryCtaAttrs, 'secondary' )
					}
				</div>
			</div>
		);
	};

	const getImageBox = () => {
		return (
			<>
				{ getImageBoxHover() }
				{ getImage() }
			</>
		);
	};

	const getInnerTopBoxContent = () => {
		switch ( style ) {
			case 'form-template':
				return getImageBox();
			case 'form-template-blank':
				return getBlankIcon();
			default:
				return null;
		}
	};

	const getExtra = () => {
		if ( style === 'form-template' ) {
			if ( ! tagAttributes || ! tagAttributes.content ) {
				return null;
			}

			const tagAttrs = {
				...tagAttributes,
				customClasses: [
					'gform-card__label',
					`gform-tag--type-gradient-${ tagAttributes.content }`,
				],
				type: 'upgrade',
			};

			return <Tag { ...tagAttrs } />;
		} else if ( style === 'form-template-blank' ) {
			return (
				<button className="gform-card__form-template-blank-button" { ...blankButtonAttributes }>
					{
						headingAttributes.content &&
						(
							<span className="gform-card__form-template-blank-button-text gform-visually-hidden">
								{ headingAttributes.content }
							</span>
						)
					}
				</button>
			);
		}
	};

	const getTopBox = () => {
		const topBoxAttrs = {
			...topBoxAttributes,
			customClasses: classnames(
				{
					'gform-card__top-container': true,
					[ `gform-util-gform-admin-background-color-${ bgColor }` ]: bgColor,
				},
				topBoxAttributes.customClasses || [],
			),
		};

		return (
			<Box { ...topBoxAttrs }>
				{ getInnerTopBoxContent() }
				{ topChildren }
			</Box>
		);
	};

	const getHeading = () => {
		if ( ! headingAttributes.content ) {
			return null;
		}

		return <Heading { ...headingAttributes } />;
	};

	const getTextContent = () => {
		if ( style !== 'form-template' ) {
			return null;
		}

		if ( ! textAttributes.content ) {
			return null;
		}

		return <Text { ...textAttributes } />;
	};

	const getBottomBox = () => {
		const bottomBoxAttrs = {
			...bottomBoxAttributes,
			customClasses: [
				'gform-card__bottom-container',
				...( bottomBoxAttributes.customClasses || [] ),
			],
		};

		return (
			<Box { ...bottomBoxAttrs }>
				{ getHeading() }
				{ getTextContent() }
				{ bottomChildren }
			</Box>
		);
	};

	const cardProps = {
		customClasses,
		...customAttributes,
		style,
	};

	return (
		<Card { ...cardProps } ref={ ref }>
			{ getExtra() }
			{ getTopBox() }
			{ getBottomBox() }
		</Card>
	);
} );

FormTemplateCard.propTypes = {
	bgColor: PropTypes.string,
	blankButtonAttributes: PropTypes.object,
	bottomBoxAttributes: PropTypes.object,
	bottomChildren: PropTypes.node,
	headingAttributes: PropTypes.object,
	imageAttributes: PropTypes.object,
	primaryCtaAttrs: PropTypes.object,
	secondaryCtaAttrs: PropTypes.object,
	style: PropTypes.string,
	tagAttributes: PropTypes.object,
	textAttributes: PropTypes.object,
	topBoxAttributes: PropTypes.object,
	topChildren: PropTypes.node,
};

FormTemplateCard.displayName = 'Cards/FormTemplateCard';

export default FormTemplateCard;
