import { h, Component, createRef } from 'preact'
import { signal } from 'preact/signals'
import htm from 'htm'
import { Node, NodeUI } from 'node'
import { ROOT_NODE } from 'node_store'
import { TreeNative } from 'tree'
const html = htm.bind(h)

export class Notes2 extends Component {
	constructor() {//{{{
		super()
		this.nodeUI = createRef()
		this.reloadTree = signal(0)
		this.state = {
			startNode: null,
		}
		this.op = signal('')
		this.treeNative = new TreeNative()

		window._sync = new Sync()
		window._sync.run()

		new OpSearch()

		this.getStartNode()
	}//}}}
	render(_props, { startNode }) {//{{{
		console.log('notes2 render')
		const treeKey = `tree-${this.reloadTree}`
		console.log('treeKey', treeKey)

		if (startNode === null)
			return

		/*
		let op = null
		switch(this.op.value) {
			case 'search':
				op = html`<${OpSearch} />`
			break
		}
		*/

		return html`
			<${Tree} app=${this} key=${treeKey} startNode=${startNode} />
			<${NodeUI} app=${this} ref=${this.nodeUI} startNode=${startNode} />
		`
	}//}}}
	getStartNode() {//{{{
		let nodeUUID = ROOT_NODE

		// Is a UUID provided on the URI as an anchor?
		const parts = document.URL.split('#')
		if (parts[1]?.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i))
			nodeUUID = parts[1]

		nodeStore.get(nodeUUID).then(node => {
			this.setState({ startNode: node })
		})
	}//}}}
	async goToNode(nodeUUID, dontPush, dontExpand) {//{{{
		if (nodeUUID === null || nodeUUID === undefined)
			return

		// Don't switch notes until saved.
		if (this.nodeUI.current.nodeModified.value) {
			if (!confirm("Changes not saved. Do you want to discard changes?"))
				return
		}

		if (!dontPush)
			history.pushState({ nodeUUID }, '', `/#${nodeUUID}`)

		// New node is fetched in order to retrieve content and files.
		// Such data is unnecessary to transfer for tree/navigational purposes.
		const node = nodeStore.node(nodeUUID)
		const ancestors = await nodeStore.getNodeAncestry(node)
		this.nodeUI.current.setNode(node)
		this.nodeUI.current.setCrumbs(ancestors)
		this.tree.setSelected(node, dontExpand)
		this.treeNative.setSelected(node, dontExpand)
	}//}}}
	logout() {//{{{
		localStorage.removeItem('session.UUID')
		location.href = '/'
	}//}}}
}

class Op {
	constructor(id) {
		this.id = id
		_mbus.subscribe(this.id, p => this.render(p))
	}
	render(html) {
		const op = document.getElementById('op')
		const t = document.createElement('template')
		t.innerHTML = `<dialog id="${this.id}" class="op">${html}</dialog>`
		op.replaceChildren(t.content)
		document.getElementById(this.id).showModal()
	}
	get(selector) {
		return document.querySelector(`#${this.id} ${selector}`)
	}
	bind(selector, event, fn) {
		this.get(selector).addEventListener(event, evt => fn(evt))
	}
}

function tmpl(html) {
	const el = document.createElement('template')
	el.innerHTML = html
	return el.content.children
}

class OpSearch extends Op {
	constructor() {
		super('op-search')
	}

	render() {
		super.render(`
			<div class="header">Search</div>
			<div>
				<input type="text" />
			</div>
			<div class="header">Results</div>
			<div class="results"></div>
		`)

		this.bind('input[type="text"]', 'keydown', evt => this.search(evt))
	}

	search(event) {
		if (event.key !== 'Enter')
			return

		const searchFor = document.querySelector('#op-search input').value
		nodeStore.search(searchFor, ROOT_NODE)
			.then(res => this.displayResults(res))
	}

	displayResults(results) {
		const rs = []
		for (const r of results) {
			const ancestors = r.ancestry.reverse().map(a => {
				const div = tmpl(`<div class="ancestor">${a.data.Name}</div>`)
				div[0].addEventListener('click', () => _notes2.current.goToNode(a.UUID))
				return div[0]
			})


			const div = tmpl(`<div>${r.name}</div>`)
			div[0].addEventListener('click', () => _notes2.current.goToNode(r.uuid))
			rs.push(...div)

			const ancDev = tmpl('<div class="ancestors"></div>')
			ancDev[0].append(...ancestors)
			rs.push(ancDev[0])
		}
		this.get('.results').replaceChildren(...rs)
	}
}

// vim: foldmethod=marker
