"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var vdom_1 = require("@dojo/framework/core/vdom");
var icache_1 = require("@dojo/framework/core/middleware/icache");
var list_1 = require("../list");
var theme_1 = require("../middleware/theme");
var focus_1 = require("@dojo/framework/core/middleware/focus");
var css = require("../theme/default/typeahead.m.css");
var trigger_popup_1 = require("../trigger-popup");
var resources_1 = require("@dojo/framework/core/middleware/resources");
var text_input_1 = require("../text-input");
var Select_1 = require("../select/nls/Select");
var i18n_1 = require("@dojo/framework/core/middleware/i18n");
var helper_text_1 = require("../helper-text");
var listCss = require("../theme/default/list.m.css");
var util_1 = require("../common/util");
var loading_indicator_1 = require("../loading-indicator");
var inputCss = require("../theme/default/text-input.m.css");
var array_1 = require("@dojo/framework/shim/array");
var factory = vdom_1.create({
    icache: icache_1.createICacheMiddleware(),
    resource: resources_1.createResourceMiddleware(),
    theme: theme_1.default,
    focus: focus_1.default,
    i18n: i18n_1.default
})
    .properties()
    .children();
exports.Typeahead = factory(function Typeahead(_a) {
    var id = _a.id, properties = _a.properties, children = _a.children, _b = _a.middleware, icache = _b.icache, resource = _b.resource, theme = _b.theme, focus = _b.focus, i18n = _b.i18n;
    var createOptions = resource.createOptions, isLoading = resource.isLoading, meta = resource.meta, find = resource.find, getOrRead = resource.getOrRead;
    var _c = properties(), initialValue = _c.initialValue, disabled = _c.disabled, required = _c.required, position = _c.position, name = _c.name, helperText = _c.helperText, itemsInView = _c.itemsInView, onValidate = _c.onValidate, _d = _c.strict, strict = _d === void 0 ? true : _d, controlledValue = _c.value, itemDisabled = _c.itemDisabled, _e = _c.resource, template = _e.template, _f = _e.options, options = _f === void 0 ? createOptions(id) : _f, classes = _c.classes, themeProp = _c.theme, variant = _c.variant;
    var themedCss = theme.classes(css);
    var messages = i18n.localize(Select_1.default).messages;
    var _g = tslib_1.__read(children(), 1), _h = _g[0], _j = _h === void 0 ? {} : _h, label = _j.label, items = _j.items, leading = _j.leading;
    if (initialValue !== undefined &&
        controlledValue === undefined &&
        initialValue !== icache.get('initial')) {
        icache.set('initial', initialValue);
        icache.set('value', initialValue);
        icache.delete('labelValue');
    }
    if (controlledValue !== undefined && icache.get('lastValue') !== controlledValue) {
        icache.set('value', controlledValue);
        icache.set('lastValue', controlledValue);
        icache.delete('labelValue');
        options({ query: { value: controlledValue } });
    }
    var valid = icache.get('valid');
    var value = icache.get('value');
    var labelValue = icache.get('labelValue');
    var listId = "typeahead-list-" + id;
    var triggerId = "typeahead-trigger-" + id;
    var dirty = icache.get('dirty');
    if (required && dirty) {
        var isValid = Boolean(value);
        if (isValid !== valid) {
            icache.set('valid', isValid);
            valid = isValid;
            onValidate && onValidate(isValid);
        }
    }
    function callOnValue(value) {
        var _a = properties(), onValidate = _a.onValidate, onValue = _a.onValue, required = _a.required;
        var lastValue = icache.get('lastValue');
        if (lastValue === value.value) {
            return;
        }
        var valid = required ? true : undefined;
        if (required && !value) {
            valid = false;
        }
        icache.set('lastValue', value.value);
        icache.set('valid', valid);
        value && onValue && onValue(value);
        onValidate && onValidate(valid);
    }
    function onKeyDown(event, preventDefault, onOpen, onClose) {
        var activeIndex = icache.getOrSet('activeIndex', 0);
        var metaInfo = meta(template, options()) || icache.get('meta');
        var total = (metaInfo && metaInfo.total) || 0;
        switch (event) {
            case util_1.Keys.Escape:
                onClose();
                break;
            case util_1.Keys.Down:
                preventDefault();
                if (!onOpen()) {
                    icache.set('activeIndex', total ? (activeIndex + 1) % total : total);
                }
                break;
            case util_1.Keys.Up:
                preventDefault();
                if (!onOpen()) {
                    icache.set('activeIndex', total ? (activeIndex - 1 + total) % total : total);
                }
                break;
            case util_1.Keys.Enter:
                preventDefault();
                icache.set('selected', true);
                onClose();
                break;
        }
    }
    var _k = options(), page = _k.page, size = _k.size;
    var index = icache.getOrSet('activeIndex', 0);
    var currentPage = Math.ceil((index + 1) / size);
    var pageIndex = Array.isArray(page)
        ? page.indexOf(currentPage) !== -1
            ? page.indexOf(currentPage)
            : 0
        : 0;
    var activeIndex = pageIndex * size + (index % size);
    var currentItems = array_1.flat(getOrRead(template, options()));
    var isCurrentlyLoading = isLoading(template, options());
    var metaInfo = icache.set('meta', function (current) {
        var newMeta = meta(template, options());
        return newMeta || current;
    });
    var activeItem = currentItems[activeIndex];
    if (icache.get('selected') && !isCurrentlyLoading) {
        if (currentItems && currentItems.length === 0) {
            if (strict) {
                if (required) {
                    valid = icache.set('valid', false);
                    onValidate && onValidate(false);
                }
            }
            else {
                var labelValue_1 = icache.getOrSet('labelValue', '');
                icache.set('value', labelValue_1);
                value = labelValue_1;
                callOnValue({ value: labelValue_1, label: labelValue_1 });
            }
            icache.set('selected', false);
        }
        else if (activeItem) {
            var disabled_1 = itemDisabled ? itemDisabled(activeItem) : !!activeItem.disabled;
            if (!disabled_1) {
                var itemValue = activeItem.value, label_1 = activeItem.label, disabled_2 = activeItem.disabled, divider = activeItem.divider;
                value = icache.set('value', activeItem.value);
                callOnValue({ value: itemValue, label: label_1, disabled: disabled_2, divider: divider });
            }
        }
        icache.set('selected', false);
    }
    return (vdom_1.tsx("div", { key: "root", classes: [
            theme.variant(),
            themedCss.root,
            disabled && themedCss.disabled,
            valid === true && themedCss.valid,
            valid === false && themedCss.invalid
        ] },
        vdom_1.tsx(trigger_popup_1.default, { key: "popup", onOpen: function () { return icache.set('expanded', true); }, onClose: function () {
                icache.set('expanded', false);
                if (!icache.get('dirty')) {
                    icache.set('dirty', true);
                }
            }, position: position, classes: classes, theme: themeProp, variant: variant }, {
            trigger: function (toggleOpen) {
                function openMenu() {
                    var disabled = properties().disabled;
                    if (!disabled && !icache.get('expanded')) {
                        toggleOpen();
                        icache.set('expanded', true);
                        icache.set('activeIndex', 0);
                        return true;
                    }
                    return false;
                }
                function closeMenu() {
                    if (icache.get('expanded')) {
                        toggleOpen();
                        icache.set('expanded', false);
                    }
                }
                var valueOption;
                if (value) {
                    var findOptions = createOptions(id + "-find");
                    valueOption = (find(template, {
                        options: findOptions({
                            page: options().page,
                            size: options().size
                        }),
                        start: 0,
                        query: { value: value },
                        type: 'exact'
                    }) || {
                        item: undefined
                    }).item;
                    if (valueOption && icache.get('labelValue') !== valueOption.label) {
                        options({ query: { label: valueOption.label } });
                    }
                }
                return (vdom_1.tsx(text_input_1.default, { autocomplete: false, onValue: function (value) {
                        openMenu();
                        options({ query: { label: value } });
                        icache.set('labelValue', value || '');
                        icache.delete('value');
                    }, theme: theme.compose(inputCss, css, 'input'), onFocus: function () {
                        var onFocus = properties().onFocus;
                        onFocus && onFocus();
                    }, onBlur: function () {
                        var onBlur = properties().onBlur;
                        if (!strict) {
                            var value_1 = icache.getOrSet('labelValue', '');
                            icache.set('value', value_1);
                            callOnValue(valueOption
                                ? {
                                    value: valueOption.value,
                                    label: valueOption.label,
                                    divider: valueOption.divider,
                                    disabled: valueOption.disabled
                                }
                                : { value: value_1, label: value_1 });
                        }
                        closeMenu();
                        onBlur && onBlur();
                    }, name: name, initialValue: valueOption ? valueOption.label : labelValue, focus: function () {
                        return icache.get('focusNode') === 'trigger' && focus.shouldFocus();
                    }, aria: {
                        controls: listId,
                        haspopup: 'listbox',
                        expanded: "" + icache.getOrSet('expanded', false)
                    }, key: "trigger", widgetId: triggerId, disabled: disabled, classes: {
                        '@dojo/widgets/text-input': {
                            root: [themedCss.trigger]
                        }
                    }, variant: variant, onClick: openMenu, onKeyDown: function (event, preventDefault) {
                        onKeyDown(event, preventDefault, openMenu, closeMenu);
                    }, valid: valid }, { label: label, leading: leading }));
            },
            content: function (toggleClosed) {
                function closeMenu() {
                    icache.set('focusNode', 'trigger');
                    toggleClosed();
                }
                var itemDisabled = properties().itemDisabled;
                return metaInfo === undefined && isLoading(template, options()) ? (vdom_1.tsx(loading_indicator_1.default, { key: "loading", theme: themeProp, classes: classes, variant: variant })) : (vdom_1.tsx("div", { key: "menu-wrapper", classes: themedCss.menuWrapper },
                    vdom_1.tsx(list_1.default, { key: "menu", focusable: false, activeIndex: icache.get('activeIndex'), resource: resource({ template: template, options: options }), disabled: itemDisabled, classes: classes, onValue: function (value) {
                            focus.focus();
                            closeMenu();
                            if (value.value !== icache.get('value')) {
                                icache.set('value', value.value);
                            }
                            callOnValue(value);
                        }, onRequestClose: closeMenu, onBlur: closeMenu, initialValue: value, itemsInView: itemsInView, theme: theme.compose(listCss, css, 'menu'), variant: variant, widgetId: listId }, items)));
            }
        }),
        vdom_1.tsx(helper_text_1.default, { key: "helperText", text: valid === false ? messages.requiredMessage : helperText, valid: valid, classes: classes, theme: themeProp, variant: variant })));
});
exports.default = exports.Typeahead;

/*# sourceMappingURL=index.js.map*/