// External dependencies.
import React, { Component } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
import debounce from "lodash/debounce";
import { __ } from "@wordpress/i18n";

const isMobileUserAgentRegExp = /mobi/i;

const FixedWidth = styled.div`
	overflow: auto;
	width: ${ ( props ) => props.widthValue }px;
	padding: 0 ${ ( props ) => props.paddingValue }px;
	max-width: 100%;
	box-sizing: border-box;
`;

const Inner = styled.div`
	width: ${ ( props ) => props.widthValue }px;
`;

const ScrollHintContainer = styled.div`
	text-align: center;
	margin: 1rem 0 0.5rem;
`;

const ScrollHint = styled.div`
	display: inline-block;
	box-sizing: border-box;

	&:before{
		display: inline-block;
		margin-right: 10px;
		font-size: 20px;
		line-height: 20px;
		vertical-align: text-top;
		content: "\\21c4";
		box-sizing: border-box;
	}
`;

/**
 * Component with a fixed width, but still make it viewable on smaller screens.
 *
 * @param {number} width Width of the component.
 * @param {number} padding Padding to add to the left and right sides.
 * @param {React.Element} children The child components.
 * @param {string} className Classname to use for the content container.
 */
export default class FixedWidthContainer extends Component {
	/**
	 * Constructs a fixed width container.
	 *
	 * @param {Object} props The props for this fixed with container.
	 *
	 * @returns {void}
	 */
	constructor( props ) {
		super( props );

		this.state = {
			showScrollHint: false,
			isMobileUserAgent: false,
		};

		this.setContainerRef = this.setContainerRef.bind( this );
		this.determineSize = debounce( this.determineSize.bind( this ), 100 );
	}

	/**
	 * Sets up the container reference and event handling.
	 *
	 * @param {HTMLElement} container The container reference.
	 *
	 * @returns {void}
	 */
	setContainerRef( container ) {
		if ( ! container ) {
			return null;
		}

		this._container = container;

		this.determineSize();

		window.addEventListener( "resize", this.determineSize );
	}

	/**
	 * Determines the size based on the container element.
	 *
	 * @returns {void}
	 */
	determineSize() {
		this.setState( {
			showScrollHint: this._container?.offsetWidth !== this._container?.scrollWidth,
			isMobileUserAgent: isMobileUserAgentRegExp.test( window?.navigator?.userAgent ),
		} );
	}

	/**
	 * Removes event listener for resizing the page.
	 *
	 * @returns {void}
	 */
	componentWillUnmount() {
		window.removeEventListener( "resize", this.determineSize );
	}

	/**
	 * @returns {React.Element} The rendered element.
	 */
	render() {
		const { width, padding, children, className, id } = this.props;

		const classNameOrId = className || id;
		const innerWidth = width - 2 * padding;

		return <div className={ `${ classNameOrId }__wrapper` }>
			<FixedWidth
				id={ id }
				className={ classNameOrId }
				widthValue={ width }
				paddingValue={ padding }
				ref={ this.setContainerRef }
			>
				<Inner
					widthValue={ innerWidth }
				>
					{ children }
				</Inner>
			</FixedWidth>
			{ this.state.showScrollHint &&
				<ScrollHintContainer>
					<ScrollHint>
						{ this.state.isMobileUserAgent
							? __( "Drag to view the full preview.", "wordpress-seo" )
							: __( "Scroll to see the preview content.", "wordpress-seo" )
						}
					</ScrollHint>
				</ScrollHintContainer>
			}
		</div>;
	}
}

FixedWidthContainer.propTypes = {
	id: PropTypes.string,
	width: PropTypes.number.isRequired,
	padding: PropTypes.number,
	children: PropTypes.node.isRequired,
	className: PropTypes.string,
};

FixedWidthContainer.defaultProps = {
	id: "",
	padding: 0,
	className: "",
};
