
import {css, html} from "../nexus/html.js"
import {interval} from "../tools/interval.js"
import {defaultNexus} from "../nexus/nexus.js"
import {RenderResult} from "../nexus/parts/types.js"
import {makeLoadingEffect} from "./make-loading-effect.js"

//
// error indicator
//

const errorStyle = css`
	:host {
		color: red;
		font-family: monospace;
	}
`

const AsciiErrorIndicator = defaultNexus.shadowView(use => (reason: string) => {
	use.name("error-indicator")
	use.styles(errorStyle)

	return html`${reason || "unknown error"}`
})

//
// loading indicator
//

const loadingStyle = css`
	:host {
		font-family: monospace;
	}
`

const AsciiLoadingIndicator = defaultNexus.shadowView(use => (hz: number, animation: RenderResult[]) => {
	use.name("loading-indicator")
	use.styles(loadingStyle)

	const frame = use.signal(0)

	use.mount(() => interval.hz(hz, () => {
		const next = frame.value + 1
		frame.value = (next < animation.length)
			? next
			: 0
	}))

	return html`${animation[frame.value]}`
})

//
// function to setup animated effects
//

export const makeAnimatedLoadingEffect = (hz: number, animation: RenderResult[]) => makeLoadingEffect({
	error: reason => AsciiErrorIndicator([reason]),
	loading: () => AsciiLoadingIndicator([hz, animation]),
})

//
// ready-made effects
//

/** animated loading indicators */
export const loading = {

	/** animated pattern that looks like "01101" */
	binary: makeAnimatedLoadingEffect(20, [
		"00000",
		"00001",
		"00010",
		"00101",
		"01011",
		"10110",
		"01100",
		"11001",
		"10011",
		"00111",
		"01110",
		"11101",
		"11011",
		"10110",
		"01101",
		"11010",
		"10100",
		"01000",
		"10000",
	]),

	/** animated braille-style spinner that looks like "⣾" */
	braille: makeAnimatedLoadingEffect(20, [
		"⣾",
		"⣷",
		"⣯",
		"⣟",
		"⡿",
		"⢿",
		"⣻",
		"⣽",
	]),
}

