import { uniqueId, useApp } from '@tldraw/editor'
import { useCallback, useRef } from 'react'

/** @public */
export function usePrint() {
	const app = useApp()
	const prevPrintEl = useRef<HTMLDivElement | null>(null)
	const prevStyleEl = useRef<HTMLStyleElement | null>(null)

	return useCallback(
		async function printSelectionOrPages() {
			const el = document.createElement('div')
			const style = document.createElement('style')

			const clearElements = (printEl: HTMLDivElement | null, styleEl: HTMLStyleElement | null) => {
				if (printEl) printEl.innerHTML = ''
				if (styleEl && document.head.contains(styleEl)) document.head.removeChild(styleEl)
				if (printEl && document.body.contains(printEl)) {
					document.body.removeChild(printEl)
				}
			}

			// Always make sure we have a clean root element.
			clearElements(prevPrintEl.current, prevStyleEl.current)
			prevPrintEl.current = el
			prevStyleEl.current = style

			// Random because this isn't for end users
			const className = `tl-print-surface-${uniqueId()}`

			el.className = className
			// NOTE: Works in most envs except safari, needs further review
			const enableMargins = false
			// NOTE: Currently buggy needs further investigation
			const allowAllPages = false
			style.innerHTML = `
			.${className} {
				display: none;
			}

			.${className} svg {
				max-width: 100%;
				height: 100%;
				display: block;
			}

			@media print {				  
				html, body {
					min-height: 100%;
					height: 100%;
					margin: 0;
				}

				body {
					position: relative;
				}

				body > * {
					display: none;
				}

				.${className} {
					display: block !important;
					background: white;
					min-height: 100%;
					height: 100%;
					max-width: 100%;
				}

				.${className}__item {
					padding: 10mm;
					display: flex;
					min-height: 100%;
					flex-direction: column;
					page-break-after: always;
					position: relative;
					overflow: hidden;
					height: 100%;
				}

				.${className}__item__main {
					flex: 1;
					display: flex;
					align-items: center;
					justify-content: center;
					max-height: 100%;
				}

				.${className}__item__header {
					display: none;
				}

				.${className}__item__footer {
					display: none;
					text-align: right;
				}

				.${className}__item__footer__hide {
					display: none;
				}

				${
					!enableMargins
						? ''
						: `
					/**
					 * Note: Safari doesn't support removing the page margins to remove them all!
					 */
					@page {
						margin:0;
					}

					.${className} .${className}__item__header {
						display: block;
					}

					.${className} .${className}__item__footer {
						display: block;
					}
				`
				}
			}

		`

			const beforePrintHandler = () => {
				document.head.appendChild(style)
				document.body.appendChild(el)
			}

			const afterPrintHandler = () => {
				app.once('change-history', () => {
					clearElements(el, style)
				})
			}

			window.addEventListener('beforeprint', beforePrintHandler)
			window.addEventListener('afterprint', afterPrintHandler)

			function addPageToPrint(title: string, footer: string | null, svg: SVGElement) {
				try {
					el.innerHTML += `<div class="${className}__item">
        <div class="${className}__item__header">
          ${title.replace(/</g, '&lt;').replace(/>/g, '&gt;')}
        </div>
        <div class="${className}__item__main">
          ${svg.outerHTML}
        </div>
        <div class="${className}__item__footer ${className}__item__footer__${footer ? '' : 'hide'}">
          ${footer ?? ''}
        </div>
      </div>`
				} catch (e) {
					console.error(e)
				}
			}

			function triggerPrint() {
				if (app.isChromeForIos) {
					beforePrintHandler()
					window.print()
				} else if (app.isSafari) {
					beforePrintHandler()
					document.execCommand('print', false)
				} else {
					window.print()
				}
			}

			const { pages, currentPageId, selectedIds } = app

			const preserveAspectRatio = 'xMidYMid meet'

			const svgOpts = {
				scale: 1,
				background: false,
				darkMode: false,
				preserveAspectRatio,
			}

			if (app.selectedIds.length > 0) {
				// Print the selected ids from the current page
				const svg = await app.getSvg(selectedIds, svgOpts)

				if (svg) {
					const page = pages.find((p) => p.id === currentPageId)
					addPageToPrint(`tldraw — ${page?.name}`, null, svg)
					triggerPrint()
				}
			} else {
				if (allowAllPages) {
					// Print all pages
					for (let i = 0; i < pages.length; i++) {
						const page = pages[i]
						const svg = await app.getSvg(app.getSortedChildIds(page.id), svgOpts)
						if (svg) {
							addPageToPrint(`tldraw — ${page.name}`, `${i}/${pages.length}`, svg)
						}
					}
					triggerPrint()
				} else {
					const page = app.currentPage
					const svg = await app.getSvg(app.getSortedChildIds(page.id), svgOpts)
					if (svg) {
						addPageToPrint(`tldraw — ${page.name}`, null, svg)
						triggerPrint()
					}
				}
			}

			window.removeEventListener('beforeprint', beforePrintHandler)
			window.removeEventListener('afterprint', afterPrintHandler)
		},
		[app]
	)
}
