// @ncadmin/views/nc-define/nc-define-methods.js

import nc from '/src/core/nc-util.js'

let updateCallback = null
let clickCallback = null
/* const ncRow = {
	component: 'nc-row',
	class: "nc-row2",
	attribute: {
		'min-height': '1em'
	}
} */

function addNode(newNode, newIndex, droppedNode) {
	if (newNode == null) {
		alert('newNode is null')
	} else {
		if (newNode.attribute.style) {
			delete newNode.attribute.style
		}
		droppedNode.children.splice(newIndex, 0, newNode) // add new node to children array, MUST use splice for Vue reactivity
	}
	updateCallback()
}

function getVueElementDepth(vueElement, rootVue, depth) {
	if (vueElement == null || vueElement.parent === rootVue) {
		return depth
	} else {
		return getVueElementDepth(vueElement.parent, rootVue, depth + 1)
	}
}

export function ncDragSetCallback(updateCallb, clickCallb) {
	updateCallback = updateCallb
	clickCallback = clickCallb
	updateCallback()
}

export const defineMethods = {
	// Vue methods
	isNcElement(node) {
		if (node.content != null || node.component.substring(0, 3) !== 'nc-') {
			// console.debug('ncElement: ', node)
			return false
		}
		return true
	},
	onClick(event) {
		event.preventDefault() // this will prevent button click to submit page
		event.stopPropagation()
		debugger
		const el = (event.item && event.item.__vue__) || event.target.__vue__ || event.target.parentNode.__vue__
		const component = el && el.ncNode && el.ncNode.component
		console.debug(`ncOnClick: '${(component || 'unknown') + ' ' + event.target.id}'`, event)
		if (el != null) {
			clickCallback(component, event.target.id)
		} else {
			debugger
		}
	},
	// sortable multiselect methods
	onSelect(event) {
		console.debug('onSelect', event)
	},
	onDeselect(event) {
		console.debug('onDeselect', event)
	},
	// normal sortable methods
	setData(event) {
		console.debug('setData', event)
	},
	onChoose(event) {
		console.debug('onChoose', event)
		this.onClick(event)
	},
	onUnchoose(event) {
		console.debug('onUnchoose', event)
	},
	onStart(event) {
		console.debug('onStart', event)
	},
	onEnd(event) {
		const droppedVue = event.to.__vue__
		console.debug('onEnd:', (droppedVue && '_uid ' + droppedVue._uid) || '- no droppedVue!', event)
		const fromVue = event.from.__vue__
		let oldIndex = event.oldDraggableIndex
		let newIndex = event.newIndex // event.newDraggableIndex
		let fromNode = fromVue.ncNode
		let droppedNode = droppedVue.ncNode
		if (fromNode == null) {
			if (droppedNode == null) {
				debugger
				// Fix code with new span.nc-define-header
				return
			}
			fromNode = fromVue.parent.ncNode
			if (fromNode == null) {
				fromNode = fromVue.parent.parent.ncNode
			}
		}
		if (droppedNode == null) {
			droppedNode = droppedVue.parent.ncNode
			if (droppedNode == null) {
				droppedNode = droppedVue.parent.parent.ncNode
			}
			if (droppedNode == null) {
				if (droppedVue === fromVue) {
					return // new element dragged, but not a good drop target
				}
				console.warn(' - onEnd - droppedNode is null, new index, event', newIndex, event)
				console.warn(' - onEnd, droppedVue:', droppedVue)
				alert('droppedNode is null')
				return
			}
		}
		if (droppedNode.children == null) {
			this.$set(droppedNode, 'children', []) // this.$set is needed for Vue reactivity
		}
		let oldArr = fromNode && fromNode.children
		if (oldIndex === newIndex && droppedNode.children === oldArr) {
			console.debug(' * onEnd - not moved, index: ', oldIndex, droppedNode.component + ' ' + droppedNode.attribute.id)
			return
		}

		let newNode // new node to add or move from old place
		if (oldArr) {
			newNode = oldArr.splice(oldIndex, 1)[0] // remove node from children array, MUST use splice for Vue reactivity
			if (newNode == null) {
				oldIndex--
				newIndex--
				newNode = oldArr.splice(oldIndex, 1)[0]
			}
			addNode(newNode, newIndex, droppedNode)
		} else {
			if (event.item && (event.items == null || event.items.length < 1)) {
				newNode = event.item.ncNode //  new item dragged from elements
				event.to.removeChild(event.item) // ••• remove new dragged element cloned 'ghost'
				addNode(newNode, newIndex, droppedNode)
			} else {
				// multidrag is available
				event.items.forEach(rec => {
					newNode = rec.ncNode //  new item dragged from elements
					event.to.removeChild(rec) // ••• remove new dragged element cloned 'ghost'
					addNode(newNode, newIndex, droppedNode)
					newIndex++
				})
			}
		}
	},
	onUpdate(event) {
		console.debug('onUpdate', event)
	},
	onSort(event) {
		console.debug('onSort', event)
	},
	onRemove(event) {
		console.debug('onRemove', event)
	},
	onFilter(event) {
		console.debug('onFilter', event)
	},
	onMove(event) {
		/* tried in: nc-sortable.js - did not work
		if (options.group && el.__vue__ && el.__vue__._name === '<NcRow>' && el.classList.contains('nc-droppable')) {
			console.debug(' - options changed to row', options.group.put)
			options.group.name = 'row'
			options.group.put = ['style', 'element']
		}
		*/
		if ((nc.isMac() ? event.originalEvent.metaKey : event.originalEvent.ctrlKey) === true) {
			console.debug('onMove - move override with command/control key')
			return true
		}
		console.debug('onMove', event)
		if (event.dragged.classList.contains('nc-row') && event.to.classList.contains('nc-row')) {
			console.debug('onMove - move denied from row to row')
			return false
		} else if (event.dragged.classList.contains('nc-col') && event.to.classList.contains('nc-col')) {
			console.debug('onMove - move denied from col to col')
			return false
		} else {
			// note: how many levels up should we test for depth? give both elements to getVueElementDepth as param?
			if (event.dragged.__vue__.parent !== event.to.__vue__.parent) {
				// skip same level test
				const draggedDepth = getVueElementDepth(event.dragged.__vue__.parent, event.dragged.__vue__.$root, 0)
				const toDepth = getVueElementDepth(event.to.__vue__.parent, event.dragged.__vue__.$root, 0)
				if (draggedDepth < toDepth) {
					return false
				}
			}
		}
		return true
	},
	onClone(event) {
		console.debug('onClone', event)
		// event.item.removeAttribute('style') // clone stays in old place, item is the moved one
	},

	onChange(event) {
		// console.debug('onChange', event) // too much calls
	}
}
