/* eslint-disable max-lines */
import './toolBar.less';
import React, { useState, useEffect } from 'react';
import _ from 'lodash';

import { Anchored, AnchoredBox, AnchoredTrigger } from '@components/Anchored.jsx';

const MAX_ZOOM = 300;
const MIN_ZOOM = 10;

const TOOLBAR_VISIBILITY = 'HB_renderer_toolbarVisibility';

const ToolBar = ({ displayOptions, onDisplayOptionsChange, visiblePages, totalPages, headerState, setHeaderState })=>{

	const [pageNum, setPageNum]     = useState(1);
	const [toolsVisible, setToolsVisible] = useState(true);

	useEffect(()=>{
		// format multiple visible pages as a range (e.g. "150-153")
		const pageRange = visiblePages.length === 1 ? `${visiblePages[0]}` : `${visiblePages[0]} - ${visiblePages.at(-1)}`;
		setPageNum(pageRange);
	}, [visiblePages]);

	useEffect(()=>{
		const Visibility = localStorage.getItem(TOOLBAR_VISIBILITY);
		if(Visibility) setToolsVisible(Visibility === 'true');

	}, []);

	const handleZoomButton = (zoom)=>{
		handleOptionChange('zoomLevel', _.round(_.clamp(zoom, MIN_ZOOM, MAX_ZOOM)));
	};

	const handleOptionChange = (optionKey, newValue)=>{
		onDisplayOptionsChange({ ...displayOptions, [optionKey]: newValue });
	};

	const handlePageInput = (pageInput)=>{
		if(/[0-9]/.test(pageInput))
			setPageNum(parseInt(pageInput)); // input type is 'text', so `page` comes in as a string, not number.
	};

	// scroll to a page, used in the Prev/Next Page buttons.
	const scrollToPage = (pageNumber)=>{
		if(typeof pageNumber !== 'number') return;
		pageNumber = _.clamp(pageNumber, 1, totalPages);
		const iframe = document.getElementById('BrewRenderer');
		const brewRenderer = iframe?.contentWindow?.document.querySelector('.brewRenderer');
		const page = brewRenderer?.querySelector(`#p${pageNumber}`);
		page?.scrollIntoView({ block: 'start' });
	};

	const calculateChange = (mode)=>{
		const iframe = document.getElementById('BrewRenderer');
		const iframeWidth = iframe.getBoundingClientRect().width;
		const iframeHeight = iframe.getBoundingClientRect().height;
		const pages = iframe.contentWindow.document.getElementsByClassName('page');

		let desiredZoom = 0;

		if(mode == 'fill'){
			// find widest page, in case pages are different widths, so that the zoom is adapted to not cut the widest page off screen.
			const widestPage = _.maxBy([...pages], 'offsetWidth').offsetWidth;

			if(displayOptions.spread === 'facing')
				desiredZoom = (iframeWidth / ((widestPage * 2) + parseInt(displayOptions.columnGap))) * 100;
			else
				desiredZoom = (iframeWidth / (widestPage + 20)) * 100;

		} else if(mode == 'fit'){
			// find the page with the largest single dim (height or width) so that zoom can be adapted to fit it.
			let minDimRatio;
			if(displayOptions.spread === 'single')
				minDimRatio = [...pages].reduce(
					(minRatio, page)=>Math.min(minRatio,
						iframeWidth / page.offsetWidth,
						iframeHeight / page.offsetHeight
					),
					Infinity
				);
			else
				minDimRatio = [...pages].reduce(
					(minRatio, page)=>Math.min(minRatio,
						iframeWidth / ((page.offsetWidth * 2) + parseInt(displayOptions.columnGap)),
						iframeHeight / page.offsetHeight
					),
					Infinity
				);

			desiredZoom = minDimRatio * 100;
		}

		const margin = 5;  // extra space so page isn't edge to edge (not truly "to fill")

		const deltaZoom = (desiredZoom - displayOptions.zoomLevel) - margin;
		return deltaZoom;
	};

	return (
		<div id='preview-toolbar' className={`toolBar ${toolsVisible ? 'visible' : 'hidden'}`} role='toolbar'>
			<div className='toggleButton'>
				<button data-tooltip-right={`${toolsVisible ? 'Hide' : 'Show'} Preview Toolbar`} 
						aria-label={`${toolsVisible ? 'Hide' : 'Show'} Preview Toolbar`} 
					    onClick={()=>{ setToolsVisible(!toolsVisible); localStorage.setItem(TOOLBAR_VISIBILITY, !toolsVisible); }}>
					<i aria-hidden='true' className='fas fa-glasses' />
				</button>
				<button data-tooltip-right={`${headerState ? 'Hide' : 'Show'} Header Navigation`} 
						aria-label={`${headerState ? 'Hide' : 'Show'} Header Navigation`} 
					    onClick={()=>{setHeaderState(!headerState);}}>
					<i aria-hidden='true' className='fas fa-rectangle-list' />
				</button>
			</div>
			{/*v=====----------------------< Zoom Controls >---------------------=====v*/}
			<div className='group' role='group' aria-label='Zoom' aria-hidden={!toolsVisible}>
				<button
					id='fill-width'
					className='tool'
					data-tooltip-bottom='Set zoom to fill preview with one page'
					aria-label='Set zoom to fill preview with one page'
					onClick={()=>handleZoomButton(displayOptions.zoomLevel + calculateChange('fill'))}
				>
					<i aria-hidden='true' className='fac fit-width' />
				</button>
				<button
					id='zoom-to-fit'
					className='tool'
					data-tooltip-bottom='Set zoom to fit entire page in preview'
					aria-label='Set zoom to fit entire page in preview'
					onClick={()=>handleZoomButton(displayOptions.zoomLevel + calculateChange('fit'))}
				>
					<i aria-hidden='true' className='fac zoom-to-fit' />
				</button>
				<button
					id='zoom-out'
					className='tool'
					onClick={()=>handleZoomButton(displayOptions.zoomLevel - 20)}
					disabled={displayOptions.zoomLevel <= MIN_ZOOM}
					data-tooltip-bottom='Zoom Out'
					aria-label='Zoom Out'
				>
					<i aria-hidden='true' className='fas fa-magnifying-glass-minus' />
				</button>
				<input
					id='zoom-slider'
					className='range-input tool hover-tooltip'
					type='range'
					name='zoom'
					list='zoomLevels'
					aria-label='Zoom Amount'
					min={MIN_ZOOM}
					max={MAX_ZOOM}
					step='1'
					value={displayOptions.zoomLevel}
					onChange={(e)=>handleZoomButton(parseInt(e.target.value))}
				/>
				<datalist id='zoomLevels'>
					<option value='100' />
				</datalist>

				<button
					id='zoom-in'
					className='tool'
					onClick={()=>handleZoomButton(displayOptions.zoomLevel + 20)}
					disabled={displayOptions.zoomLevel >= MAX_ZOOM}
					data-tooltip-bottom='Zoom In'
					aria-label='Zoom In'
				>
					<i aria-hidden='true' className='fas fa-magnifying-glass-plus' />
				</button>
			</div>

			{/*v=====----------------------< Spread Controls >---------------------=====v*/}
			<div className='group' role='group' aria-label='Spread' aria-hidden={!toolsVisible}>
				<div className='radio-group' role='radiogroup'>
					<button role='radio'
						id='single-spread'
						className='tool'
						data-tooltip-bottom='Single Page'
						aria-label='Single Page Spread'
						onClick={()=>{handleOptionChange('spread', 'single');}}
						aria-checked={displayOptions.spread === 'single'}
					><i aria-hidden='true' className='fac single-spread' /></button>
					<button role='radio'
						id='facing-spread'
						className='tool'
						data-tooltip-bottom='Facing Pages'
						aria-label='Facing Pages Spread'
						onClick={()=>{handleOptionChange('spread', 'facing');}}
						aria-checked={displayOptions.spread === 'facing'}
					><i aria-hidden='true' className='fac facing-spread' /></button>
					<button role='radio'
						id='flow-spread'
						className='tool'
						data-tooltip-bottom='Flow Pages'
						aria-label='Flow Pages Spread'
						onClick={()=>{handleOptionChange('spread', 'flow');}}
						aria-checked={displayOptions.spread === 'flow'}
					><i aria-hidden='true' className='fac flow-spread' /></button>

				</div>
				<Anchored>
					<AnchoredTrigger id='spread-settings' className='tool' aria-label='Spread options' data-tooltip-bottom='Spread options'>
						<i aria-hidden='true' className='fas fa-gear' />
					</AnchoredTrigger>
					<AnchoredBox>
						<h1>Options</h1>
						<label data-tooltip-left='Modify the horizontal space between pages.'>
							Column gap
							<input type='range' min={0} max={200} defaultValue={displayOptions.columnGap || 10} className='range-input' onChange={(evt)=>handleOptionChange('columnGap', evt.target.value)} />
						</label>
						<label data-tooltip-left='Modify the vertical space between rows of pages.'>
							Row gap
							<input type='range' min={0} max={200} defaultValue={displayOptions.rowGap || 10} className='range-input' onChange={(evt)=>handleOptionChange('rowGap', evt.target.value)} />
						</label>
						<label data-tooltip-left='Start 1st page on the right side, such as if you have cover page.'>
							Start on right
							<input type='checkbox' checked={displayOptions.startOnRight} onChange={()=>{handleOptionChange('startOnRight', !displayOptions.startOnRight);}}
								data-tooltip-right={displayOptions.spread !== 'facing' ? 'Switch to Facing to enable toggle.' : null} />
						</label>
						<label data-tooltip-left='Toggle the page shadow on every page.'>
							Page shadows
							<input type='checkbox' checked={displayOptions.pageShadows} onChange={()=>{handleOptionChange('pageShadows', !displayOptions.pageShadows);}} />
						</label>
					</AnchoredBox>
				</Anchored>
			</div>

			{/*v=====----------------------< Page Controls >---------------------=====v*/}
			<div className='group' role='group'  aria-label='Pages' aria-hidden={!toolsVisible}>
				<button
					id='previous-page'
					className='previousPage tool'
					type='button'
					data-tooltip-bottom='Previous Page(s)'
					aria-label='Previous Page'
					onClick={()=>scrollToPage(_.min(visiblePages) - visiblePages.length)}
					disabled={visiblePages.includes(1)}
				>
					<i aria-hidden='true' className='fas fa-arrow-left'></i>
				</button>

				<div className='tool'>
					<input
						id='page-input'
						className='text-input'
						type='text'
						name='page'
						data-tooltip-bottom='Current page(s) in view'
						aria-label='Current page in view'
						inputMode='numeric'
						pattern='[0-9]'
						value={pageNum}
						onClick={(e)=>e.target.select()}
						onChange={(e)=>handlePageInput(e.target.value)}
						onBlur={()=>scrollToPage(pageNum)}
						onKeyDown={(e)=>e.key == 'Enter' && scrollToPage(pageNum)}
						style={{ width: `${pageNum.length}ch` }}
					/>
					<span id='page-count' aria-label={`${totalPages} Total Pages`} data-tooltip-bottom='Total Page Count'><span aria-hidden='true'>/ {totalPages}</span></span>
				</div>

				<button
					id='next-page'
					className='tool'
					type='button'
					data-tooltip-bottom='Next Page(s)'
					aria-label='Next Page'
					onClick={()=>scrollToPage(_.max(visiblePages) + 1)}
					disabled={visiblePages.includes(totalPages)}
				>
					<i aria-hidden='true' className='fas fa-arrow-right'></i>
				</button>
			</div>
		</div>
	);
};

export default ToolBar;
