export class SelectNodeDialog {
	constructor(callback) {// {{{
		this.selectType = new SelectType
		this.searchResults = null
		this.searchText = null
		this.selectType = null
		this.nodeTable = null
		this.moreExist = null

		if (callback !== undefined)
			this.callback = callback
		else
			this.callback = () => { }
	}// }}}
	async render() {// {{{
		const dlg = document.createElement('dialog')
		dlg.id = 'select-node'
		dlg.addEventListener('close', () => dlg.remove())

		dlg.innerHTML = `
			<div class="label">Search for node</div>
			<input class="search-text" type="text" placeholder="Search" />
			<select></select>
			<div style="display: grid; grid-template-columns: min-content 1fr; align-items: center; grid-gap: 16px;">
				<button>Search</button>
				<div class="more-exist"></div>
			</div>
			<div class="search-results"></div>
		`

		this.nodeTable = new NodeTable((_node, node) => {
			this.callback(node)
			dlg.close()
		})

		this.searchText = dlg.querySelector('.search-text')
		this.searchResults = dlg.querySelector('.search-results')
		this.moreExist = dlg.querySelector('.more-exist')
		const button = dlg.querySelector('button')
		button.addEventListener('click', () => this.search())

		this.searchText.addEventListener('keydown', event => {
			if (event.key === 'Enter')
				this.search()
		})
		this.searchText.focus()
		this.searchText.value = '%'

		new SelectType(true).render()
			.then(select => {
				this.selectType = select
				dlg.querySelector('select').replaceWith(this.selectType)
			})

		document.body.appendChild(dlg)
		dlg.showModal()
	}// }}}
	search() {// {{{
		const type_id = this.selectType.value
		const search = this.searchText.value
		this.moreExist.innerText = ''

		fetch(`/nodes/search?` + new URLSearchParams({ type_id, search }))
			.then(data => data.json())
			.then(json => {
				if (!json.OK) {
					showError(json.Error)
					return
				}

				this.nodeTable.clearNodes()
				this.nodeTable.addNodes(json.Nodes)
				this.searchResults.replaceChildren(this.nodeTable.render())

				if (json.MoreExistThan > 0)
					this.moreExist.innerText = `Only displaying ${json.MoreExistThan} nodes. There are more matching the given criteria.`
			})
			.catch(err => showError(err))
	}// }}}
}

export class SelectType {
	constructor(allowNoType) {// {{{
		this.allowNoType = allowNoType
	}// }}}
	async render() {// {{{
		return new Promise((resolve, reject) => {
			this.fetchTypes()
				.then(types => {
					const select = document.createElement('select')

					if (this.allowNoType) {
						const option = document.createElement('option')
						option.setAttribute('value', -1)
						option.innerText = '[ No specific type ]'
						select.appendChild(option)
					}

					types.sort(_app.typeSort)
					let prevGroup = null
					for (const t of types) {
						if (t.Name == 'root_node')
							continue

						if (t.Schema['x-group'] != prevGroup) {
							prevGroup = t.Schema['x-group']
							const group = document.createElement('optgroup')
							group.setAttribute('label', t.Schema['x-group'])
							select.appendChild(group)
						}

						const opt = document.createElement('option')
						opt.setAttribute('value', t.ID)
						opt.innerHTML = '&nbsp;&nbsp;&nbsp;&nbsp;' + (t.Schema.title || t.Name)
						select.appendChild(opt)
					}

					resolve(select)
				})
				.catch(err => reject(err))
		})
	}// }}}
	async fetchTypes() {// {{{
		return new Promise((resolve, reject) => {
			fetch('/types/')
				.then(data => data.json())
				.then(json => {
					if (!json.OK) {
						showError(json.Error)
						return
					}
					resolve(json.Types)
				})
				.catch(err => reject(err))
		})
	}// }}}
}

class NodeTable {
	constructor(callback) {// {{{
		this.nodes = new Map()

		if (callback !== undefined)
			this.callback = callback
		else
			this.callback = () => { }
	}// }}}
	render() {// {{{
		const div = document.createElement('div')
		div.classList.add('node-table')

		for (const k of Array.from(this.nodes.keys())) {
			const group = document.createElement('div')
			group.classList.add('group')
			group.innerHTML = `
				<div class="label">${k}</div>
				<div class="children"></div>
			`

			const groupChildren = group.querySelector('.children')
			for (const n of this.nodes.get(k)) {
				const icon = document.createElement('img')
				icon.setAttribute('src', `/images/${_VERSION}/node_modules/@mdi/svg/svg/${n.TypeIcon}.svg`)
				icon.addEventListener('click', event => this.callback(event, n))

				const node = document.createElement('div')
				node.classList.add('node')
				node.innerText = n.Name
				node.addEventListener('click', event => this.callback(event, n))

				groupChildren.appendChild(icon)
				groupChildren.appendChild(node)
			}

			div.appendChild(group)
		}

		return div
	}// }}}
	clearNodes() {// {{{
		this.nodes = new Map()
	}// }}}
	addNodes(nodes) {// {{{
		for (const n of nodes) {
			let tableNodes = this.nodes.get(n.TypeSchema.title)
			if (tableNodes === undefined) {
				tableNodes = []
				this.nodes.set(n.TypeSchema.title, tableNodes)
			}
			tableNodes.push(n)
		}
	}// }}}
}

export class ConnectionDataDialog {
	constructor(node, callback) {// {{{
		this.node = node
		this.callback = callback
	}// }}}
	render() {// {{{
		const dlg = document.createElement('dialog')
		dlg.id = 'connection-data'
		dlg.addEventListener('close', () => dlg.remove())

		dlg.innerHTML = `
			<div>
				<div style="float: left;" class="label">Connection data</div>
				<div style="float: right;">
					<div class="tooltip left" data-tooltip="Delete the connection">
						<img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/trash-can.svg" />
					</div>
				</div>
			</div>
			<div style="clear: both;"><b>${this.node.Name}</b></div>
			<div><textarea></textarea></div>
			<div class="button"><button>Update</button></div>
		`
		dlg.querySelector('textarea').value = JSON.stringify(this.node.ConnectionData, null, 4)

		dlg.querySelector('img').addEventListener('click', ()=>{
			if(!confirm('Do you want to delete the connection?'))
				return

			fetch(`/connection/delete/${this.node.ConnectionID}`)
				.then(data => data.json())
				.then(json => {
					if (!json.OK) {
						showError(json.Error)
						return
					}
					dlg.close()
					this.callback()
				})
				.catch(err => showError(err))
		})

		dlg.querySelector('button').addEventListener('click', () => {
			// Connection data is updated.
			fetch(`/connection/update/${this.node.ConnectionID}`, {
				method: 'POST',
				body: dlg.querySelector('textarea').value,
			})
				.then(data => data.json())
				.then(json => {
					if (!json.OK) {
						showError(json.Error)
						return
					}
					dlg.close()
					this.callback()
				})
				.catch(err => showError(err))
		})

		document.body.appendChild(dlg)
		dlg.showModal()
	}// }}}
}

// vim: foldmethod=marker
