import {
	reconstituteTable,
	TableEmoji,
	TableHeaderDataset,
	tableIdentifier,
	type TableProps,
	TableTitle
} from './TableHeader';
import {
	GeneratedResult,
	type GeneratedResultProps, type GeneratedResultPropsFull,
	type PartialGeneratedResultProps, type PartialGeneratedResultPropsFull,
	reconstituteGeneratedResult
} from './GeneratedResult';
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import { pulseElement } from './pulseElement';

export type GeneratedElementPropsBase = {
	table: TableProps
	selected: boolean|null
} & GeneratedResultProps

export type GeneratedElementEditableProps = GeneratedElementPropsBase & { selected: boolean } & GeneratedResultPropsFull
export type GeneratedElementReadonlyProps = GeneratedElementPropsBase & { selected: null } & GeneratedResultProps

export type GeneratedElementProps = GeneratedElementEditableProps|GeneratedElementReadonlyProps

export type PartialGeneratedElementProps = PartialGeneratedElementEditableProps|PartialGeneratedElementReadonlyProps

export type PartialGeneratedElementEditableProps = {
	table?: Partial<TableProps>
	selected?: boolean
} & PartialGeneratedResultPropsFull

export type PartialGeneratedElementReadonlyProps = {
	table?: Partial<TableProps>
	selected?: null
} & PartialGeneratedResultProps

export function reconstituteGeneratedElement(element: HTMLLIElement, partial?: PartialGeneratedElementProps): GeneratedElementProps {
	const result = reconstituteGeneratedResult(element.querySelector(".generatedResult")!, partial)
	const selected = typeof partial?.selected !== 'undefined'
		? partial.selected
		: (element.querySelector<HTMLInputElement>('.generatedSelect')?.checked) ?? null
	const table = reconstituteTable(element.querySelector(".tableHeader")!, partial?.table)
	if (result.set) {
		return {
			...result,
			table,
			selected,
		}
	} else {
		return {
			...result,
			table,
			selected: null,
		}
	}
}

export interface GeneratedElementEvents {
	onSelectionChange?: (tableId: number, selected: boolean) => void
}

export function GeneratedElement({ onSelectionChange, ...props }: GeneratedElementProps & GeneratedElementEvents) {
	const ref = useRef<HTMLInputElement>(null);
	const selected = props.selected
	const [lastSelected, setLastSelected] = useState(selected)
	const tableId = tableIdentifier(props.table)
	const checkId = `selected-${tableId}`
	const changeCallback = useCallback((ev: Event) => {
		if (onSelectionChange && typeof props.table.id === "number") {
			onSelectionChange(props.table.id, (ev.currentTarget as HTMLInputElement).checked)
		}
	}, [onSelectionChange])
	useEffect(() => {
		if (selected !== lastSelected) {
			setLastSelected(selected)
			if (ref.current) {
				pulseElement(ref.current)
			}
		}
	}, [ref, selected, lastSelected, setLastSelected])
	return <li class="generatedElement" id={`generated-${tableIdentifier(props.table)}`}>
		<h2 class="generatedHead">
			<label
				class="generatedLabel tableHeader"
				{...(props.selected !== null ? {"for": checkId} : {})}
				{...TableHeaderDataset(props.table)}>
				<TableEmoji {...props.table} />
				{' '}
				<TableTitle {...props.table} />
			</label>
			<input type="checkbox" class={`generatedSelect${props.selected === null ? " unselectable" : ""}`}
								 id={checkId}
						     name={checkId}
						     checked={props.selected ?? false}
						     onChange={changeCallback}
								 ref={ref} />
		</h2>
		<GeneratedResult {...props} />
	</li>
}
