'use strict';

const React = require("react");
const useMeasure = require("react-use-measure");
const matchValue = require("match-value");
const insecureNanoid = require("nanoid/non-secure").nanoid;

const defaultStyle = require("./style.css");
const useTheme = require("../../util/themeable");
const useGuaranteedMemo = require("../../util/use-guaranteed-memo");
const isEventInsideRef = require("../../util/is-event-inside-ref");
const comparePath = require("../../util/compare-path");
const MenuItemContext = require("../../contexts/menu-item");
const MenuPositionContext = require("../../contexts/menu-position");
const MenuPathContext = require("../../contexts/menu-path");

module.exports = function MenuItem({ label, title, menu, onClick }) {
	let { withTheme } = useTheme({ control: "menu", defaultStyle });
	let [ boundsRef, bounds ] = useMeasure({ debounce: 10 });
	let submenuRef = React.useRef();
	let itemContext = React.useContext(MenuItemContext);
	let path = React.useContext(MenuPathContext);
	let id = useGuaranteedMemo(() => insecureNanoid()); // insecure is fine here, these IDs are not interesting to an attacker

	let ownPath = path.concat([ id ]); // FIXME: memoize?
	let isSelected = itemContext.isActive && comparePath(itemContext.selectedPath, ownPath);

	let submenuPosition = matchValue(itemContext.menuType, {
		menuBar: {
			x: bounds.x,
			y: bounds.y + bounds.height
		},
		menu: {
			x: bounds.x + bounds.width, /* FIXME: Account for border of containing menu? */
			y: bounds.y
		}
	});

	let handlers = {
		onClick: (event) => {
			if (!isEventInsideRef(submenuRef, event)) {
				if (onClick != null) {
					onClick(); // TODO: Pass through event? Allow cancellation? To deal with advanced cases like checkboxes within menus, if we want that
				}

				if (itemContext.onClick != null) {
					let hasMenu = (menu != null);
					let isInMenu = false; // Let the menu intercept and change this
					
					itemContext.onClick(ownPath, hasMenu, isInMenu);
				}
			}
		},
		onMouseEnter: (_event) => {
			// FIXME: Only outside of submenu?
			if (itemContext.onMouseEnter != null) {
				itemContext.onMouseEnter(ownPath);
			}
		},
		onMouseLeave: (_event) => {
			// FIXME: Only outside of submenu?
			if (itemContext.onMouseLeave != null) {
				itemContext.onMouseLeave(ownPath);
			}
		},
	};

	let buttonClasses = withTheme([
		"item",
		{ item_selected: isSelected },
		{ item_directPress: (menu == null) }
	]);

	return (
		<MenuPathContext.Provider value={ownPath}>
			<MenuPositionContext.Provider value={submenuPosition}>
				<div ref={boundsRef} title={title} className={buttonClasses} {...handlers}>
					{label}

					{(menu != null)
						? <span className={withTheme("submenu")} ref={submenuRef}>
							<i className={withTheme("submenuArrow")}>▶</i>
							{(isSelected)
								? menu
								: null
							}
						</span>
						: null
					}
				</div>
			</MenuPositionContext.Provider>
		</MenuPathContext.Provider>
	);
};
