// form/nc/nc-define/nc-layout-editor/nc-layout-editor.js
// preference/form/nc/nc-define/nc-layout-editor/nc-layout-editor.js
// /src/components/nc-define/nc-layout/nc-layout-editor.vue

import { initKeyboard, keyEvent, selectEvent } from '/plugin/nc-layout-editor/nc-layout-keyboard.js'
import { restCallback, setIdAndAttribute, toggleFocus, hoverBoxStyle, propertyComponentName, loadPropertyComponent } from '/plugin/nc-layout-editor/nc-layout-editor-util.js'
// import NcLayoutToolbar from '/plugin/nc-layout-editor/nc-layout-toolbar.js'
// import NcLayoutContent from '/plugin/nc-layout-editor/nc-layout-content.js'

console.debug('• nc-layout-editor lazy-loaded')

const props = defineProps({
	layout: {
		type: String,
		default: undefined,
		description: 'Layout to load.'
	}
})

function preloadPropertyComponent() {
	for (const name of rec.preload_component) {
		loadPropertyComponent(nc, rec, propertyComponentName(name))
	}
}
// preloadPropertyComponent()

initKeyboard(state)
const layoutEvent = ref({ type: '', ncNode: null })
provide('layout-event', layoutEvent)

const emptyLayout = {
	name: '',
	layout: {
		component: 'nc-form',
		element: [{ component: 'nc-row' }]
	}
}

let toolbarWidth = ref('0em')
const layout = ref({})
// const layoutHtml = ref('')
// const layoutJson = ref()
let prevComponent
watch(
	() => props.layout + rec.layout_name + rec.layout_component,
	() => {
		if (props.layout) {
			rec.layout_name = peg.parseBeforeLast(props.layout, '/')
		}
		if (prevComponent !== rec.layout_component && rec.layout_component !== '') {
			prevComponent = rec.layout_component
			loadLayout(rec.layout_component, true)
		} else if (prevComponent !== rec.layout_name) {
			prevComponent = rec.layout_name
			loadLayout(rec.layout_name)
		}
	},
	{ immediate: true }
)

watch(
	() => rec.show_tools + rec.tool_column_count,
	() => {
		showTools(rec.show_tools + rec.tool_column_count) // param is needed for watchEffect to fire
	},
	{ immediate: true }
)

function showTools() {
	if (rec.show_tools) {
		toolbarWidth.value = rec.element_column_width * rec.tool_column_count + rec.toolbar_extra_width + 'em'
	} else {
		toolbarWidth.value = '0em'
	}
}

const displayNoneStyle = { display: 'none' }
const noHoverNode = {}

// eslint-disable-next-line no-unused-vars
function onHover() {
	// called from html
	hoverBoxStyle.value = displayNoneStyle
	state.rec.hover_node = noHoverNode
}

onMounted(() => {
	window.addEventListener('keydown', event => {
		hoverBoxStyle.value = displayNoneStyle
		if (event.target === document.body) {
			keyEvent(event, rec.selected_node)
		} else {
			const area = event.target.closest('#nc-layout-area') // check if event is inside drawing area
			if (area) {
				keyEvent(event, rec.selected_node)
				/* const ret = keyEvent(event, rec.selected_node)
				if (ret === 'ok') {
					event.target.blur() // move focus away from input, but inputs are not enabled
				} */
			}
		}
	})
})

watch(layoutEvent, () => {
	const node = layoutEvent.value.ncNode
	if (node) {
		console.debug('* layout event', layoutEvent.value.type, node.component)
		selectEvent(node, state)
	}
})

function onClick(event) {
	// usually onClick goes to nc-layout-content.js, here comes clicks that do not go to elements
	const ncNode = event.target.ncNode // parentElement(event.target)
	if (ncNode) {
		console.debug(`onClick:editor ${ncNode.component + ' ' + ncNode.id}`, event, ncNode)
		layoutEvent.value = { type: 'onClick:editor', ncNode: ncNode, event: event }
	}
}

// eslint-disable-next-line no-unused-vars
function onDoubleClick() {
	toggleFocus(state)
}

function redraw(newLayout) {
	rec.selected_node = {}
	const json = newLayout.layout.layout
	let contentRecursion = true
	if (state.rec.layout_name === 'form/nc/nc-define/nc-layout-editor/nc-layout-content' || state.rec.layout_name === 'form/nc/nc-define/nc-layout-editor') {
		contentRecursion = false
	}
	setIdAndAttribute(
		json,
		[
			{
				component: ['nc-input', 'nc-label-input', 'nc-textarea', 'nc-label-textarea', 'nc-dropdown', 'nc-label-dropdown'],
				attribute: { focus: onFocus } // onFocus will do elem.blur() to unfocus, we don't want to enter in input elements
			}
		],
		contentRecursion
	)
	nc.setRec(state, 'layout_json', json) // toolbar save needs this
	if (newLayout.layout_component) {
		nc.setArr(state, 'layout_component', newLayout.layout_component)
		nc.setRec(state, 'layout_component', newLayout.layout_component[0].value)
	}
	nc.setRec(state, 'layout', newLayout.layout)
	if (newLayout.layout_name) {
		nc.setRec(state, 'layout_name', newLayout.layout_name)
	}
	// nc.setRec(state, 'javascript', newLayout.javascript)
	layout.value = json // trigger redraw
	setTimeout(() => {
		// wait for first redraw, it will set .ncElem tag to design area
		layoutEvent.value = { type: 'update', ncNode: layout.value.ncElem && layout.value.ncElem.ncNode }
		const el = document.getElementById('nc-layout-area')
		if (el) {
			el.focus({ preventScroll: true }) // focus and blur to set focus to design area so that user can start moving with arrows
			el.blur()
		}
	}, 0)
}

function loadLayout(layoutName, isComponent) {
	if (!layoutName) {
		nc.setArr(state, 'layout_component', [
			{
				show: '',
				value: ''
			}
		])
		nc.setRec(state, 'layout_component', '')
		redraw({ layout: nc.clone(emptyLayout) })
	} else {
		nc.callServer(state, 'dynamic-form', { path: layoutName, return: ['layout', 'layout_component'], component: isComponent }, ret => {
			if (ret.layout) {
				redraw(ret)
			} else {
				restCallback(state)() // restCallback return function
			}
		})
	}
}

function onFocus(event) {
	console.log('onFocus ', event.target.nodeName, event)
	const ncNode = event.target.ncNode
	console.debug(`onFocus:editor '${ncNode && ncNode.component}'`, event)
	event.target.blur()
	onClick(event)
	return false // false == do not run default code
}
