<template>
<div :class="mainClass">
    <div class="navStack" v-if="stack.length">
        <transition-group name="fadeInDown" tag="ul">
            <li v-for="(si, index) in stack" :key="si.code" @click.stop="moveUpMenu(index)">{{si.label}}<Icon :icon="['fabt', 'chevron-up']" class="navIcon"/></li>
        </transition-group>
    </div>
    <div class="navMain">
        <transition-group name="list" tag="div">
            <div v-for="(g, idx) in current" :key="'GRP_'+idx" :class="g.isGrouped ? 'grouped' : ''">
                <h4 v-if="g.isGrouped">{{g.groupHead}}</h4>
                <ul>
                    <li v-for="(h, idy) in g.items" :key="idy" @click.stop="h.hasChild ? moveInMenu(h.code) : relayEvent(h.code)">{{h.text}} <Icon :icon="['fabt', 'chevron-right']" class="navIcon" v-if="h.hasChild"/></li>
                </ul>
            </div>
        </transition-group>
    </div>
</div>
</template>

<script>
import { isArray, isEmpty, groupBy, forEach, delay } from 'lodash'
import { FontAwesomeIcon as Icon } from '@fortawesome/vue-fontawesome'

function nodeTraversal(code, tree) {
	let obj = null

	function recurse(nodes) {
		for (let i = 0; i < nodes.length; i++) {
			if (nodes[i].code == code) {
				obj = nodes[i]
				break
			} else if (nodes[i].options.length) {
				recurse(nodes[i].options)
			}
		}
	}
	recurse(tree)

	return obj
}
export default {
	name: 'DrawerNavMenu',
	components: {
		Icon
	},
	props: {
		id: {
			type: String,
			required: true
		},
		param: {
			type: Array,
			required: true
		},
		theme: {
			type: String,
			default: 'bt',
			validator: function (val) {
				return ['bt', 'dark', 'light'].indexOf(val) !== -1
			}
		}
	},
	data() {
		return {
			stack: [],
			current: []
		}
	},
	computed: {
		mainClass() {
			return 'navMenu ' + this.theme
		}
	},
	methods: {
		initMenu() {
			this.stack = []
			this.current = []
			this.moveInMenu()
		},
		moveUpMenu(idx) {
			if (idx == 0) {
				this.stack = []
			} else {
				this.stack.splice(idx)
			}
			if (this.stack.length) {
				this.moveInMenu(this.stack[this.stack.length - 1].parent)
			} else {
				this.moveInMenu(null)
			}
		},
		moveInMenu(code) {
			if (code) {
				this.formCurrent(nodeTraversal(code, this.param))
			} else {
				this.formCurrent(this.param)
			}
		},
		formCurrent(obj) {
			this.current = []
			let collect = []
			if (isArray(obj) && !isEmpty(obj)) {
				let grouped = groupBy(obj, 'group')
				forEach(grouped, (v, k) => {
					let o = { isGrouped: false, groupHead: null, items: [] }
					if (k && k != 'undefined') {
						o.isGrouped = true
						o.groupHead = k
						v.forEach(i => {
							if (!i.disable) {
								o.items.push({ code: i.code, text: i.label, hasChild: i.options && i.options.length > 0 })
							}
						})
					} else {
						v.forEach(i => {
							if (!i.disable) {
								o.items.push({ code: i.code, text: i.label, hasChild: i.options && i.options.length > 0 })
							}
						})
					}
					collect.push(o)
				})
			} else if (!isEmpty(obj)) {
				if (this.stack.length) {
					this.stack.push({ code: obj.code, label: obj.label, parent: this.stack[this.stack.length - 1].code })
				} else {
					this.stack.push({ code: obj.code, label: obj.label, parent: null })
				}
				let grouped = groupBy(obj.options, 'group')
				forEach(grouped, (v, k) => {
					let o = { isGrouped: false, groupHead: null, items: [] }
					if (k && k != 'undefined') {
						o.isGrouped = true
						o.groupHead = k
						v.forEach(i => {
							if (!i.disable) {
								o.items.push({ code: i.code, text: i.label, hasChild: i.options && i.options.length > 0 })
							}
						})
					} else {
						v.forEach(i => {
							if (!i.disable) {
								o.items.push({ code: i.code, text: i.label, hasChild: i.options && i.options.length > 0 })
							}
						})
					}
					collect.push(o)
				})
			}
			delay(() => {
				this.current = collect
			}, 500)
		},
		relayEvent(code) {
			this.$emit('input', code)
			this.$emit('change', code)
		}
	},
	mounted() {
		this.$events.on(`resetMenu|${this.id}`, this.initMenu)
	},
	beforeDestroy() {
		this.$events.off(`resetMenu|${this.id}`)
	},
	watch: {
		param: {
			handler: 'initMenu',
			immediate: true
		}
	}
}
</script>
