import {StateManager} from "/js/state_manager.mjs"
import {StateManagerProtected} from "/js/state_manager_protected.mjs"
import * as hakuban from "https://cdn.jsdelivr.net/npm/hakuban@0.8.1/hakuban-with-wasm.js"
import { NavigationState, NavigationError } from "/js/navigation_state.mjs"
import { navigation_objectify } from "/js/navigation_state.mjs"
import { ApplicationState } from "/js/application_state.mjs"


function update_links(ul_id, new_state, options = {}) {
	const a_attrs = new_state.hrefs(options)
	let a = document.querySelector(`#${ul_id} .internal-href`)
	for (const key in a_attrs) a.setAttribute(key, a_attrs[key])
	a.textContent = JSON.stringify(a_attrs).substring(0, 100)
	a = document.querySelector(`#${ul_id} .external-href`)
	for (const key in a_attrs) a.setAttribute(key, a_attrs[key])
	a.textContent = JSON.stringify(a_attrs).substring(0, 100)
	const url = new_state.url()
	a = document.querySelector(`#${ul_id} .external-url`)
	if (url === undefined) {
		a.removeAttribute("href")
		a.textContent = "---"
	} else {
		a.setAttribute("href", url)
		a.textContent = JSON.stringify(url).substring(0, 100)
	}

	a = document.querySelector(`#${ul_id} .internal-js`)
	a.onclick = ()=> new_state.navigate_to(options)
}


export async function start() {
	await hakuban.initialize("info")
	let hakuban_exchange = new hakuban.Exchange()
	const dynamic = window.location.pathname.includes("dynamic")

	let manager_builder = StateManager.build()
		.exposing([["exposed", "expose"]])
		.with_hakuban_exchange(hakuban_exchange)
		//.with_mountpoint("/navigation-browser.html")
		.with_url_shortener("http://localhost:3003/")
		.with_navigation_state_sanitizer((editable_navstate) => {
			editable_navstate.keep_only_values(["scope", "limited_value_1"], ["a", "b"])
			editable_navstate.keep_only_values("limited_value_2", ["a", "b"])
			editable_navstate.keep_only_keys("limited_keys_scope",["a", "b"])
		})
	manager_builder = dynamic ? manager_builder.with_dynamic_pathname() : manager_builder.with_static_pathname()
	const manager = manager_builder.run()

	window.manager = manager
	document.manager = manager
	window.url_shortened = ()=> manager[StateManagerProtected.shortened]()

	document.getElementById("loaded-timestamp").textContent = new Date().toISOString()

	manager.state.cache.ts = "never"
	manager.state.scope("scoped").cache.tss = "never"

	let itt = manager.states();
	for await (let state of itt) {
		const timestamp = new Date().toISOString()
		window.state = state

		if (!dynamic && window.location.pathname.slice(1).includes("/")) {
			document.getElementById("error").innerHTML = "STATIC manager generated /-containing url"
			continue
		}

		if (dynamic && window.location.pathname.slice(1).includes("#")) {
			document.getElementById("error").innerHTML = "DYNAMIC manager generated #-containing url"
			continue
		}

		const previous_timestamp = document.getElementById("change-counter").textContent
		if (state.cache.ts != previous_timestamp || state.scope("scoped").cache.tss != previous_timestamp) {
			document.getElementById("error").innerHTML = `Cache values are invalid: ${JSON.stringify(state.cache.ts)} ${JSON.stringify(state.scope("scoped").cache.tss)}, should be: ${JSON.stringify(previous_timestamp)}`
			continue
		}

		document.title = "Test: "+JSON.stringify(state.navigation)
		if (state.navigation === undefined) continue

		let objectified_state = navigation_objectify(state.navigation)
		if (objectified_state.type == 'NavigationError') delete objectified_state['stack']
		document.getElementById("state").innerHTML = JSON.stringify(objectified_state)
		document.getElementById("scope-value-state").innerHTML = JSON.stringify(state.scope("scope").navigation?.get?.("value"))
		console.log("new state", state)

		if (state.navigation instanceof NavigationError) {
			document.getElementById("error").innerHTML = JSON.stringify(state.navigation.message)
		} else {
			document.getElementById("error").innerHTML = ""
		}
		//console.log(state)

		const navstate = (state.navigation instanceof NavigationError) ? NavigationState.create().set("removed", "abc").set("error", state.navigation.kind) : state.navigation
		const scoped_state = (state.navigation instanceof NavigationError) ? (new ApplicationState(null, [], NavigationState.create().set("removed", "abc").set("error", state.navigation.kind).scope("scope").root_scope())) : state
		const scoped_navstate = scoped_state.scope("scope").navigation
		console.log("navstates", navstate, scoped_navstate)
		update_links("no-op", navstate)
		update_links("append", navstate.set("appended", "x"))
		update_links("remove", navstate.remove("removed", "y"))
		update_links("too-long-for-href", navstate.set("appended-too-long", "x".repeat(2000)))
		update_links("append-private", navstate.private_set("appended-private", "px"))
		update_links("remove-private", navstate.private_remove("removed-private", "py"))
		update_links("append-scoped", scoped_navstate.set("value", "x"))
		update_links("append-exposed", navstate.set("expose", "nice"))
		update_links("append-delayed", navstate.set("appended", timestamp), { commit_delay: 2000 })
		update_links("append-squashed", navstate.set("appended", timestamp), { squashable: 2000 })

		document.getElementById("load").textContent = "loaded"
		//document.getElementById("change-counter").textContent = (parseInt(document.getElementById("change-counter").textContent) + 1).toString()

		document.getElementById("change-counter").textContent = timestamp
		state.cache.ts = timestamp
		state.scope("scoped").cache.tss = timestamp

	}

	throw "exited"
}
