import classnames from 'classnames/dedupe';
import { debounce } from 'throttle-debounce';

import apiFetch from '@wordpress/api-fetch';
import {
	BaseControl,
	Button,
	ButtonGroup,
	TextControl,
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { RawHTML, useState } from '@wordpress/element';
import { addFilter } from '@wordpress/hooks';
import { __, sprintf } from '@wordpress/i18n';

import Notice from '../components/notice';
import controlGetValue from '../utils/control-get-value';

const { VPGutenbergVariables } = window;

const NOTICE_LIMIT = parseInt(
	VPGutenbergVariables.items_count_notice_limit,
	10
);
const DISPLAY_NOTICE_AFTER = NOTICE_LIMIT + 5;

function getNoticeState() {
	return VPGutenbergVariables.items_count_notice;
}

const maybeUpdateNoticeStateMeta = debounce(3000, (postId) => {
	apiFetch({
		path: '/visual-portfolio/v1/update_gallery_items_count_notice_state',
		method: 'POST',
		data: {
			notice_state: getNoticeState(),
			post_id: postId,
		},
	});
});

function updateNoticeState(postId) {
	const newState = getNoticeState() === 'hide' ? 'show' : 'hide';

	VPGutenbergVariables.items_count_notice = newState;

	maybeUpdateNoticeStateMeta(postId);
}

function CountNotice(props) {
	const { onToggle, postId } = props;

	return (
		<Notice status="warning" isDismissible={false}>
			<p
				dangerouslySetInnerHTML={{
					__html: __(
						'Using large galleries may <u>decrease page loading speed</u>. We recommend you add these improvements:',
						'visual-portfolio'
					),
				}}
			/>
			<ol className="ol-decimal">
				<li
					dangerouslySetInnerHTML={{
						__html: sprintf(
							__(
								'Set the items per page to <u>less than %d</u>',
								'visual-portfolio'
							),
							NOTICE_LIMIT
						),
					}}
				/>
				<li
					dangerouslySetInnerHTML={{
						__html: __(
							'Add <em>`Load More`</em> or <em>`Infinite Scroll`</em> pagination for best results.',
							'visual-portfolio'
						),
					}}
				/>
			</ol>
			<p>
				<Button
					isLink
					onClick={() => {
						updateNoticeState(postId);
						onToggle();
					}}
				>
					{__('Ok, I understand', 'visual-portfolio')}
				</Button>
			</p>
		</Notice>
	);
}

function shouldDisplayNotice(count, attributes) {
	let display = false;

	// When selected images number is lower, then needed, don't display notice, even is count is large.
	if (attributes.content_source === 'images') {
		display =
			attributes?.images?.length > DISPLAY_NOTICE_AFTER &&
			(count > DISPLAY_NOTICE_AFTER || count === -1);
	} else {
		display = count > DISPLAY_NOTICE_AFTER || count === -1;
	}

	return display;
}

function ItemsCountControl({ data }) {
	const { description, attributes, onChange } = data;

	const [maybeReRender, setMaybeReRender] = useState(1);

	const { postId } = useSelect(
		(select) => ({
			postId: select('core/editor')?.getCurrentPostId() || false,
		}),
		[]
	);

	const renderControlHelp = description ? (
		<RawHTML>{description}</RawHTML>
	) : (
		false
	);
	const renderControlClassName = classnames(
		'vpf-control-wrap',
		`vpf-control-wrap-${data.type}`
	);
	const controlVal = parseInt(controlGetValue(data.name, attributes), 10);

	return (
		<BaseControl
			id="vpf-control-items-count-all"
			label={
				<>
					{data.label}
					{getNoticeState() === 'hide' &&
					shouldDisplayNotice(controlVal, attributes) ? (
						<Button
							onClick={() => {
								updateNoticeState(postId);
								setMaybeReRender(maybeReRender + 1);
							}}
							style={{
								position: 'absolute',
								marginTop: '-5px',
								padding: '0 4px',
								color: '#cd7a0f',
							}}
						>
							<svg
								xmlns="http://www.w3.org/2000/svg"
								height="16"
								width="16"
								viewBox="0 0 24 24"
								fill="red"
							>
								<path
									d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"
									fill="currentColor"
								/>
							</svg>
						</Button>
					) : null}
				</>
			}
			help={renderControlHelp}
			className={renderControlClassName}
			__nextHasNoMarginBottom
		>
			<div>
				<ButtonGroup>
					<Button
						variant={controlVal !== -1 ? 'primary' : ''}
						isPressed={controlVal !== -1}
						onClick={() => {
							if (controlVal === -1) {
								onChange(parseFloat(data.default || 6));
							}
						}}
					>
						{__('Custom Count', 'visual-portfolio')}
					</Button>
					<Button
						variant={controlVal === -1 ? 'primary' : ''}
						isPressed={controlVal === -1}
						onClick={() => {
							if (
								controlVal !== -1 &&
								// eslint-disable-next-line no-alert
								window.confirm(
									__(
										'Be careful, the output of all your items can adversely affect the performance of your site, this option may be helpful for image galleries.',
										'visual-portfolio'
									)
								)
							) {
								onChange(-1);
							}
						}}
					>
						{__('All Items', 'visual-portfolio')}
					</Button>
				</ButtonGroup>
			</div>
			{controlVal !== -1 ? (
				<>
					<br />
					<TextControl
						type="number"
						min={data.min}
						max={data.max}
						step={data.step}
						value={controlVal}
						onChange={(val) => onChange(parseFloat(val))}
						__next40pxDefaultSize
						__nextHasNoMarginBottom
					/>
				</>
			) : null}
			{getNoticeState() === 'show' &&
			shouldDisplayNotice(controlVal, attributes) ? (
				<div>
					<CountNotice
						postId={postId}
						onToggle={() => {
							setMaybeReRender(maybeReRender + 1);
						}}
					/>
				</div>
			) : null}
		</BaseControl>
	);
}

// Items count with "All Items" button.
addFilter(
	'vpf.editor.controls-render',
	'vpf/editor/controls-render/customize-controls',
	(render, data) => {
		if (data.name !== 'items_count') {
			return render;
		}

		return (
			<ItemsCountControl
				// we should use key prop, since `vpf.editor.controls-render` will use the result in array.
				key={`control-${data.name}-${data.label}`}
				data={data}
			/>
		);
	}
);
