import { type Signal, useComputed, useSignal } from '@preact/signals'
import { useEffect } from 'preact/hooks'
import { IS_BROWSER } from '$fresh/runtime.ts'

type NetworkConnection = {
	addEventListener: (
		type: 'change',
		listener: (event: Event) => void | Promise<void>,
	) => void
}

export default function IsOnline(
	{ online, offline }: { online?: string; offline: string },
) {
	if (!IS_BROWSER) {
		return online
			? <span style={{ display: 'none' }}></span>
			: <span>{online}</span>
	}

	const status = useSignal(true)
	const displayed = useComputed(() => {
		if (status.value && online) {
			return <span>{online}</span>
		}
		if (status.value) {
			return <span style={{ display: 'none' }}></span>
		}
		return <span class={'island__is_online'}>{offline}</span>
	})
	const connection = 'connection' in navigator
		? navigator.connection as NetworkConnection
		: null
	useEffect(() => {
		openSocket(status, { id: undefined })
		connection?.addEventListener('change', () => {
			fetch('/api/serviceworker/is-online')
				.then(() => status.value = true)
				.catch(() => status.value = false)
		})
	}, [])

	return <>{displayed}</>
}

function openSocket(status: Signal<boolean>, ref: { id: number | undefined }) {
	const socket = new WebSocket(
		`wss://${location.host}/api/serviceworker/is-online`,
	)
	socket.addEventListener('open', () => {
		status.value = true
		clearInterval(ref.id)
	})
	socket.addEventListener('close', () => {
		status.value = false
		// Try reconnect every 5s
		const id = setInterval(() => openSocket(status, ref), 5_000)
		ref.id = id
	})
}
