"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vue_1 = require("vue");
const vdirs_1 = require("vdirs");
const treemate_1 = require("treemate");
const utils_1 = require("../../select/src/utils");
const _internal_1 = require("../../_internal");
const _utils_1 = require("../../_utils");
const utils_2 = require("./utils");
const interface_1 = require("./interface");
exports.default = (0, vue_1.defineComponent)({
    name: 'NCascaderSelectMenu',
    props: {
        value: {
            type: [String, Number, Array],
            default: null
        },
        show: Boolean,
        pattern: {
            type: String,
            default: ''
        },
        multiple: Boolean,
        tmNodes: {
            type: Array,
            default: () => []
        },
        filter: Function,
        labelField: {
            type: String,
            required: true
        },
        separator: {
            type: String,
            required: true
        }
    },
    setup(props) {
        const { isMountedRef, mergedValueRef, mergedClsPrefixRef, mergedThemeRef, mergedCheckStrategyRef, slots: cascaderSlots, syncSelectMenuPosition, closeMenu, handleSelectMenuClickOutside, doUncheck: cascaderDoUncheck, doCheck: cascaderDoCheck, clearPattern } = (0, vue_1.inject)(interface_1.cascaderInjectionKey);
        const menuInstRef = (0, vue_1.ref)(null);
        const selectOptionsRef = (0, vue_1.computed)(() => {
            return (0, utils_2.createSelectOptions)(props.tmNodes, mergedCheckStrategyRef.value === 'child', props.labelField, props.separator);
        });
        const mergedFilterRef = (0, vue_1.computed)(() => {
            const { filter } = props;
            if (filter)
                return filter;
            const { labelField } = props;
            return (pattern, _, path) => path.some(option => option[labelField]
                && ~option[labelField]
                    .toLowerCase()
                    .indexOf(pattern.toLowerCase()));
        });
        const filteredSelectOptionsRef = (0, vue_1.computed)(() => {
            const { pattern } = props;
            const { value: mergedFilter } = mergedFilterRef;
            return (pattern
                ? selectOptionsRef.value.filter((option) => {
                    return mergedFilter(pattern, option.rawNode, option.path);
                })
                : selectOptionsRef.value).map(option => ({
                value: option.value,
                label: option.label
            }));
        });
        const selectTreeMateRef = (0, vue_1.computed)(() => {
            return (0, treemate_1.createTreeMate)(filteredSelectOptionsRef.value, (0, utils_1.createTmOptions)('value', 'children'));
        });
        function handleResize() {
            syncSelectMenuPosition();
        }
        function handleToggle(tmNode) {
            doCheck(tmNode);
        }
        // We don't care what type the tmNode is, we only care about its key
        function doCheck(tmNode) {
            if (props.multiple) {
                const { value: mergedValue } = mergedValueRef;
                if (Array.isArray(mergedValue)) {
                    if (!mergedValue.includes(tmNode.key)) {
                        cascaderDoCheck(tmNode.key);
                    }
                    else {
                        cascaderDoUncheck(tmNode.key);
                    }
                }
                else if (mergedValue === null) {
                    cascaderDoCheck(tmNode.key);
                }
                clearPattern();
            }
            else {
                cascaderDoCheck(tmNode.key);
                // currently the select menu is set to focusable
                // however just leave it here
                closeMenu(true);
            }
        }
        function prev() {
            var _a;
            (_a = menuInstRef.value) === null || _a === void 0 ? void 0 : _a.prev();
        }
        function next() {
            var _a;
            (_a = menuInstRef.value) === null || _a === void 0 ? void 0 : _a.next();
        }
        function enter() {
            var _a;
            if (menuInstRef) {
                const pendingOptionTmNode = (_a = menuInstRef.value) === null || _a === void 0 ? void 0 : _a.getPendingTmNode();
                if (pendingOptionTmNode) {
                    doCheck(pendingOptionTmNode);
                }
                return true;
            }
            return false;
        }
        function handleClickOutside(e) {
            handleSelectMenuClickOutside(e);
        }
        const exposedRef = {
            prev,
            next,
            enter
        };
        return Object.assign({ isMounted: isMountedRef, mergedTheme: mergedThemeRef, mergedClsPrefix: mergedClsPrefixRef, menuInstRef, selectTreeMate: selectTreeMateRef, handleResize,
            handleToggle,
            handleClickOutside,
            cascaderSlots }, exposedRef);
    },
    render() {
        const { mergedClsPrefix, isMounted, mergedTheme, cascaderSlots } = this;
        return ((0, vue_1.h)(vue_1.Transition, { name: "fade-in-scale-up-transition", appear: isMounted }, {
            default: () => this.show
                ? (0, vue_1.withDirectives)((0, vue_1.h)(_internal_1.NInternalSelectMenu, { ref: "menuInstRef", onResize: this.handleResize, clsPrefix: mergedClsPrefix, class: `${mergedClsPrefix}-cascader-menu`, autoPending: true, themeOverrides: mergedTheme.peerOverrides.InternalSelectMenu, theme: mergedTheme.peers.InternalSelectMenu, treeMate: this.selectTreeMate, multiple: this.multiple, value: this.value, onToggle: this.handleToggle }, {
                    empty: () => (0, _utils_1.resolveSlot)(cascaderSlots['not-found'], () => [])
                }), [
                    [
                        vdirs_1.clickoutside,
                        this.handleClickOutside,
                        undefined,
                        { capture: true }
                    ]
                ])
                : null
        }));
    }
});
