/**메뉴의 생성과 선택 시 동작을 지원한다.
 */
class MenuSupport {
	/**새 MenuSupport를 생성한다.
	 * @param selector {string} 메뉴를 담을 컨테이너에 대한 css selector
	 */
	constructor(selector) {
		this._container = document.querySelector(this._selector = selector);
		this._horizontal = this._container && this._container.classList.contains('menu-horizontal');
		this._orientation = this._horizontal ? "horizontal" : "vertical";
		this._template = this._orientation + "-menu-template";
		this._menuItem = '<li data-key="{menuID}" class="menu-item"><a href="{url}" class="menu-link{toggle}"><i class="menu-icon tf-icons bx bx-layout"></i><div data-i18n="{menuName}">{menuName}</div></a>{menuSub}</li>';
    	this._menuSub = '<ul class="menu-sub">{children}</ul>';
		this._menus = [];
	}

	/**메뉴를 생성할 정보를 설정한다.
	 * @param menus {array} 메뉴 정보 배열<br />
     * 각 메뉴 정보의 레이아웃은 다음과 같다.<br />
     * {"id":메뉴 아이디, "name":"메뉴 이름", "url":"실행 url", "parentID":"상위 메뉴 아이디", "description":"메뉴 설명", "imagePath":"이미지 경로", "displayWindow":"표시 창", "children":[하위 메뉴 배열]}
     * @returns MenuSupport
	 */
	setMenuInfo(menus) {
		let setParent = menu => {
			let children = menu.children || [];
			if (children.length < 1) return;
			
			children.forEach(child => {
				child.parent = menu;
				setParent(child);
			});
		};
		menus.forEach(menu => setParent(menu));
		this._menus = menus;
		
		let menuItemTag = menu => {
			let tag = this._menuItem
				.replace(/{menuID}/gi, menu.id)
				.replace(/{menuName}/gi, menu.name)
				.replace(/{url}/gi, !menu.url ? "javascript:void(0);" : wctx.url(menu.url));
			let parent = menu.children && menu.children.length > 0;
			tag = tag.replace(/{toggle}/gi, !parent ? "" : " menu-toggle");
			if (!parent)
				return tag.replace(/{menuSub}/gi, "");
			
			let children = menu.children.map(child => menuItemTag(child)).join("\n\t")
			return tag.replace(/{menuSub}/gi, this._menuSub.replace(/{children}/gi, children));
		}
		let tags = (menus || []).map(menu => menuItemTag(menu));
		document.querySelector("#menus").innerHTML = tags.join("");
		
		return this._init();
	}
	
	_init() {
		document.querySelectorAll(this._selector).forEach(element => {
		  let menu = new Menu(element, {
		    orientation: this._orientation,
		    closeChildren: this._horizontal,
		    showDropdownOnHover: localStorage.getItem('templateCustomizer-' + this._template + '--ShowDropdownOnHover')
		      ? localStorage.getItem('templateCustomizer-' + this._template + '--ShowDropdownOnHover') === 'true'
		      : window.templateCustomizer !== undefined
		      ? window.templateCustomizer.settings.defaultShowDropdownOnHover
		      : true
		  });
		  
		  window.Helpers.scrollToActive(false); //animate = false
		  window.Helpers.mainMenu = menu;
		});
		//Sets toggler
		document.querySelectorAll('.layout-menu-toggle').forEach(item => {
		  item.addEventListener('click', event => {
		    event.preventDefault();
		    window.Helpers.toggleCollapsed();
		    if (config.enableMenuLocalStorage && !window.Helpers.isSmallScreen()) {
		      try {
		        localStorage.setItem(
		          'templateCustomizer-' + this._template + '--LayoutCollapsed',
		          String(window.Helpers.isCollapsed())
		        );
		      } catch (e) {}
		    }
		  });
		});
		// Display menu toggle (layout-menu-toggle) on hover with delay
		let delay = (elem, callback) => {
		  let timeout = null;
		  elem.onmouseenter = () => {
		    // Set timeout to be a timer which will invoke callback after 300ms (not for small screen)
		    timeout = !Helpers.isSmallScreen() ? setTimeout(callback, 300) : setTimeout(callback, 0);
		  };

		  elem.onmouseleave = () => {
		    // Clear any timers set to timeout
		    document.querySelector('.layout-menu-toggle').classList.remove('d-block');
		    clearTimeout(timeout);
		  };
		};
		if (this._container) {
		  delay(this._container, () => {
		    // not for small screen
		    if (!Helpers.isSmallScreen()) {
		      document.querySelector('.layout-menu-toggle').classList.add('d-block');
		    }
		  });
		}
		
		return this;
	}

	/**지정한 url의 메뉴를 활성화 한다.
	 * @param url {string} 메뉴 url
     * @returns MenuSupport
	 */
	setActive(url) {
		document
			.querySelectorAll(this._selector + " li")
			.forEach(li => li.classList.remove("active", "open"));
		
		let a = document.querySelector(this._selector + ' a[href=\"' + wctx.url(url) + '\"]');
		if (!a) return this;
		
		let activate = (e, open) => {
			let p = e.parentNode;
			let tag = (p != this._container ? p : null) ? p.tagName : "";
			if (!tag) return;
			
			if ("li" == tag.toLowerCase()) {
				p.classList.add("active");
				if (open)
					p.classList.add("open");
			}
			activate(p, true);
				
		};
		
		activate(a);
		
		return this;
	}

	/**지정하는 url의 메뉴 정보를 반환한다.
	 * @param url {string} 메뉴 url
     * @returns 지정하는 url의 메뉴 정보
	 */	
	getMenu(url) {
		let find = menus => {
			for (let i = 0; i < menus.length; ++i) {
				let menu = menus[i];
				if (url == menu.url)
					return menu;
				let found = find(menu.children || []);
				if (found)
					return found;
			}
			return null;
		};
		return find(this._menus);
	}
	
	breadcrumb(url, separator = " / ") {
		let menu = this.getMenu(url);
		if (!menu)
			return "";
			
		let getName = menu => {
			let name = menu.name;
			let parent = !menu.parent ? "" : getName(menu.parent);
			return parent ? parent + separator + name : name;
		} 
		
		return getName(menu);
	}
}