import { CustomHTMLElement } from "./lib/custom_html_element.mjs"
import { API } from './api.mjs'

export class N2PagePreferences extends CustomHTMLElement {
	static {// {{{
		this.tmpl = document.createElement('template')
		this.tmpl.innerHTML = `
			<style>
				.el-sets {
					display: grid;
					grid-template-columns: min-content;
					grid-gap: 32px;
				}

				:host > div {
					margin-bottom: 32px;
				}

				.dev-pref-set {
					display: grid;
					grid-template-columns: min-content min-content;
					grid-gap: 16px;
					align-items: center;
					white-space: nowrap;
				}
			</style>
			<h1>Preferences</h1>

			<div>Changes preferences to not download images or files on the device doesn't remove the already downloaded data.</div>

			<div class="dev-pref-set">
				<div>Device preference set</div>
				<select data-el="dev-preference-set"></select>
			</div>

			<div data-el="sets"></div>

			<button data-el="new-set">New set</button>
			<button data-el="save" disabled>Save</button>
		`
	}// }}}
	constructor() {// {{{
		super(true)
		this.sets = []

		this.elNewSet.addEventListener('click', () => this.newSet())
		this.elSave.addEventListener('click', () => this.save())
		this.elDevPreferenceSet.addEventListener('change', ()=>this.changePreferenceSet())

		window._mbus.subscribe('SHOW_PAGE', async event => {
			if (event.detail.data?.page == 'preferences') {
				this.sets = await this.getPreferenceSets()
				this.render()
			}
		})

		window._mbus.subscribe('PREFERENCE_SET_MODIFIED', () => this.preferencesModified())
		window._mbus.subscribe('PREFERENCE_SET_DELETE', event => this.preferencesDelete(event.detail.data.set))
	}// }}}
	sortSets(a, b) {// {{{
		if (a.name == 'default') return -1
		if (b.name == 'default') return 1

		if (a.name.toLowerCase() < b.name.toLowerCase()) return -1
		if (a.name.toLowerCase() > b.name.toLowerCase()) return 1

		return 0
	}// }}}
	async render() {// {{{
		try {
			this.sets.sort(this.sortSets)
			this.elSets.replaceChildren(...this.sets)
			
			const setNames = this.sets.entries().map(([_idx, set]) => {
				const optn = document.createElement('option')
				optn.innerText = set.name
				return optn
			})
			this.elDevPreferenceSet.replaceChildren(...setNames)
		} catch (e) {
			console.error(e)
			alert(e.message)
		}
	}// }}}
	async getPreferenceSets() {// {{{
		const userData = localStorage.getItem('user')
		if (userData === null)
			throw new Error('Could not find user in localStorage')

		const user = JSON.parse(userData)
		const prefsData = user.Preferences

		if (prefsData === undefined)
			throw new Error('User object is missing preferences')

		if (!prefsData.hasOwnProperty('default'))
			throw new Error('The "default" preferences set is missing')

		return Object.keys(prefsData).map(name => new N2PreferenceSet(name, prefsData[name]))
	}// }}}
	async retrieveServerPreferences() {// {{{
		try {
			API.query('GET', '/user/preferences')
		} catch (e) {
			console.error(e)
			alert(`Error retrieving preferences: ${e.message}`)
		}
	}// }}}
	changePreferenceSet() {// {{{
		this.preferencesModified()
	}// }}}
	newSet() {// {{{
		let name = prompt("Name for new preference set")
		if (!name)
			return

		name = name.trim()
		if (name === '')
			return

		if (name == 'default') {
			alert(`Name can't be "default".`)
			return
		}

		const exists = this.sets.some(s => s.name.toLowerCase() == name.toLowerCase())
		if (exists) {
			alert(`Set with name "${name}" already exist.`)
			return
		}

		this.sets.push(new N2PreferenceSet(name, {}))
		this.preferencesModified()
		this.render()
	}// }}}
	preferencesModified() {// {{{
		this.elSave.removeAttribute('disabled')
	}// }}}
	preferencesDelete(deleteSet) {// {{{
		if (deleteSet.name == 'default') {
			alert("Can't delete the default set.")
			return
		}

		if (!confirm(`Confirm deleting "${deleteSet.name}"`))
			return

		this.sets = this.sets.filter(set => {
			return !(set.name === deleteSet.name)
		})

		this.preferencesModified()
		this.render()
	}// }}}
	async save() {// {{{
		try {
			let newPrefs = {}
			this.sets.forEach(s => {
				const setState = s.getState()
				newPrefs[setState.name] = setState.state
			})

			// Throws exception on both HTTP and application errors.
			await API.query('POST', '/user/preferences', newPrefs)

			const userData = localStorage.getItem('user')
			const user = JSON.parse(userData)
			user.Preferences = newPrefs
			localStorage.setItem('user', JSON.stringify(user))
			localStorage.setItem('device_preference_set', this.elDevPreferenceSet.value)

			// Application is told that reloading preferences is to be done.
			_mbus.dispatch('DEVICE_PREFERENCE_SET_UPDATED')
		} catch (e) {
			console.error(e)
			alert(e.message)
		} finally {
			this.elSave.setAttribute('disabled', true)
		}

	}// }}}
}
customElements.define('n2-pagepreferences', N2PagePreferences)

// Preferences is a set of preferences, of which there can be many named.
export class N2PreferenceSet extends CustomHTMLElement {
	static {// {{{
		this.tmpl = document.createElement('template')
		this.tmpl.innerHTML = `
			<style>
				:host {
					border: 1px solid var(--line-color);
					padding: 16px;

					display: grid;
					grid-template-columns: min-content 1fr;
					justify-items: start;
					align-items: center;
					grid-gap: 8px 16px;
					white-space: nowrap;
					user-select: none;

					.header {
						grid-column: 1 / -1;
						width: 100%;

						display: grid;
						grid-template-columns: 1fr min-content;

						.el-name {
							font-weight: bold;
							margin-bottom: 32px;
							cursor: pointer;
							color: var(--color1);
						}

						.el-delete {
							cursor: pointer;
						}
					}
				}

			</style>

			<div class="header">
				<div data-el="name"></div>
				<div data-el="delete">✘</div>
			</div>

			<div><label for="download-images">Download images on device</label></div>
			<input data-field="download-images" type="checkbox" id="download-images">

			<div><label for="download-files">Download files on device</label></div>
			<input data-field="download-files" type="checkbox" id="download-files">
		`
	}// }}}
	constructor(name, data) {// {{{
		super(true)
		this.name = name
		this.data = data
		this.render()

		// Enable the save button when settings are modified.
		this.allFields().forEach(f =>
			f.addEventListener('input', () => _mbus.dispatch('PREFERENCE_SET_MODIFIED'))
		)

		this.elName.addEventListener('click', () => this.updateName())
		this.elDelete.addEventListener('click', () => this.deleteSet())
	}// }}}
	updateName() {// {{{
		if (this.name == 'default') {
			alert('Can not change name of the default profile.')
			return
		}

		const name = prompt("Change name", this.name)
		if (!name)
			return

		this.name = name
		this.render()
		_mbus.dispatch('PREFERENCE_SET_MODIFIED')
	}// }}}
	deleteSet() {// {{{
		_mbus.dispatch('PREFERENCE_SET_DELETE', { set: this })
	}// }}}
	render() {// {{{
		this.elName.innerText = this.name

		this.fieldDownloadImages.checked = this.data.DownloadImages
		this.fieldDownloadFiles.checked = this.data.DownloadFiles
	}// }}}
	getState() {// {{{
		const name = this.name.trim()
		if (name === '')
			throw new Error('Name can not be empty.')

		return {
			name: this.name.trim(),
			state: this.fieldValues(),
		}
	}// }}}
}
customElements.define('n2-preferenceset', N2PreferenceSet)
