"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 icon_1 = require("../icon");
var iconCss = require("../theme/default/icon.m.css");
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 _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 ? resource.createOptions(function (curr, next) { return (tslib_1.__assign({}, curr, next)); }) : _f, classes = _c.classes, themeProp = _c.theme, variant = _c.variant, hasDownArrow = _c.hasDownArrow, kind = _c.kind;
    var _g = resource.template(template), get = _g.get, read = _g.template.read;
    var themedCss = theme.classes(css);
    var messages = i18n.localize(Select_1.default).messages;
    var _h = tslib_1.__read(children(), 1), _j = _h[0], _k = _j === void 0 ? {} : _j, label = _k.label, items = _k.items, leading = _k.leading;
    if (initialValue !== undefined &&
        controlledValue === undefined &&
        initialValue !== icache.get('initial')) {
        icache.set('initial', initialValue);
        icache.set('value', initialValue);
        icache.delete('labelValue');
    }
    var updatedValue = icache.get('lastValue') !== controlledValue;
    if (controlledValue !== undefined && updatedValue) {
        icache.set('value', controlledValue);
        icache.set('lastValue', controlledValue);
        icache.delete('labelValue');
        icache.set('selectedOption', function (option) {
            if (option && option.value !== controlledValue) {
                return undefined;
            }
            return option;
        });
        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');
    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 _a = get(options(), { meta: true, read: read }).meta.total, total = _a === void 0 ? 0 : _a;
        switch (event) {
            case util_1.Keys.Escape:
                onClose();
                break;
            case util_1.Keys.Down:
                preventDefault();
                if (!onOpen()) {
                    icache.set('activeIndex', function (activeIndex) {
                        if (activeIndex === void 0) { activeIndex = strict ? 0 : -1; }
                        return total ? (activeIndex + 1) % total : total;
                    });
                }
                break;
            case util_1.Keys.Up:
                preventDefault();
                if (!onOpen()) {
                    icache.set('activeIndex', function (activeIndex) {
                        if (activeIndex === void 0) { activeIndex = 0; }
                        activeIndex = activeIndex === -1 ? 0 : activeIndex;
                        return total ? (activeIndex - 1 + total) % total : total;
                    });
                }
                break;
            case util_1.Keys.Tab:
            case util_1.Keys.Enter:
                preventDefault();
                var activeIndex = icache.getOrSet('activeIndex', strict ? 0 : -1);
                var labelValue_1 = icache.get('labelValue');
                if (activeIndex > -1 || labelValue_1) {
                    var data = get(tslib_1.__assign({}, options(), { size: total }));
                    var selectedValue = void 0;
                    var activeItem = data[activeIndex];
                    if (strict) {
                        if (!data.length) {
                            if (required) {
                                icache.set('valid', false);
                                onValidate && onValidate(false);
                            }
                            options({ query: {} });
                            icache.set('labelValue', '');
                        }
                        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;
                                selectedValue = { value: itemValue, label: label_1, disabled: disabled_2, divider: divider };
                            }
                        }
                    }
                    else {
                        if (activeItem) {
                            var disabled_3 = itemDisabled
                                ? itemDisabled(activeItem)
                                : !!activeItem.disabled;
                            if (!disabled_3) {
                                var itemValue = activeItem.value, label_2 = activeItem.label, disabled_4 = activeItem.disabled, divider = activeItem.divider;
                                selectedValue = { value: itemValue, label: label_2, disabled: disabled_4, divider: divider };
                            }
                        }
                        if (!selectedValue && labelValue_1) {
                            selectedValue = array_1.find(data, function (item) {
                                if (item) {
                                    return item.label.toLowerCase() === labelValue_1.toLowerCase();
                                }
                                return false;
                            });
                            if (!selectedValue) {
                                selectedValue = { value: labelValue_1, label: labelValue_1 };
                            }
                        }
                    }
                    if (selectedValue) {
                        icache.set('value', selectedValue.value);
                        icache.set('selectedOption', selectedValue);
                        callOnValue(selectedValue);
                    }
                }
                onClose();
                break;
        }
    }
    var _l = get(options(), { meta: true, read: read }).meta, total = _l.total, status = _l.status;
    var selectedOption = icache.get('selectedOption');
    if (required && dirty) {
        var isValid = Boolean(selectedOption) || Boolean(!strict && !!labelValue);
        if (isValid !== valid) {
            icache.set('valid', isValid);
            valid = isValid;
            onValidate && onValidate(isValid);
        }
    }
    if (!icache.get('selectedOption') && value) {
        var currentItems = get(options(), { read: read }) || [];
        var option = currentItems.find(function (item) { return Boolean(item && item.value === value); });
        if (option) {
            icache.set('selectedOption', option);
        }
        else {
            var findItem = get(tslib_1.__assign({}, options(), { query: tslib_1.__assign({}, options().query, { value: value }) }), { read: read }) || [];
            if (findItem) {
                icache.set('selectedOption', findItem[0]);
            }
        }
    }
    var expanded = icache.get('expanded');
    var focused = icache.get('focused');
    return (vdom_1.tsx("div", { key: "root", classes: [
            theme.variant(),
            themedCss.root,
            disabled && themedCss.disabled,
            valid === true && themedCss.valid,
            valid === false && themedCss.invalid,
            expanded && themedCss.expanded,
            focused && themedCss.focused
        ] },
        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', strict ? 0 : -1);
                        return true;
                    }
                    return false;
                }
                function closeMenu() {
                    if (icache.get('expanded')) {
                        toggleOpen();
                        icache.set('expanded', false);
                    }
                    if (!icache.get('dirty')) {
                        icache.set('dirty', true);
                    }
                }
                var selectedOption = icache.get('selectedOption');
                return (vdom_1.tsx(text_input_1.default, { autocomplete: false, onValue: function (value) {
                        openMenu();
                        options({ query: { label: value } });
                        icache.set('labelValue', value || '');
                        icache.set('activeIndex', strict ? 0 : -1);
                        icache.delete('value');
                        icache.delete('selectedOption');
                    }, theme: theme.compose(inputCss, css, 'input'), onFocus: function () {
                        var onFocus = properties().onFocus;
                        icache.set('focused', true);
                        onFocus && onFocus();
                    }, onBlur: function () {
                        var onBlur = properties().onBlur;
                        icache.set('focused', false);
                        if (!strict) {
                            var value_1 = icache.getOrSet('labelValue', '');
                            var currentOption = icache.get('selectedOption');
                            var selectedOption_1 = icache.set('selectedOption', function (selectedOption) {
                                if (selectedOption) {
                                    return selectedOption;
                                }
                                if (value_1) {
                                    return { value: value_1, label: value_1 };
                                }
                            });
                            icache.set('value', selectedOption_1 ? selectedOption_1.value : value_1);
                            if (selectedOption_1) {
                                if (!currentOption ||
                                    currentOption.value !== selectedOption_1.value) {
                                    callOnValue(selectedOption_1);
                                }
                            }
                        }
                        closeMenu();
                        onBlur && onBlur();
                    }, name: name, value: selectedOption ? selectedOption.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, kind: kind }, {
                    label: label,
                    leading: leading,
                    trailing: hasDownArrow && (vdom_1.tsx("button", { type: "button", disabled: disabled, classes: themedCss.arrow, onclick: openMenu, onkeydown: function (event) {
                            if (event.which === util_1.Keys.Down ||
                                event.which === util_1.Keys.Space ||
                                event.which === util_1.Keys.Enter) {
                                event.preventDefault();
                                openMenu();
                            }
                        } },
                        vdom_1.tsx(icon_1.default, { type: "downIcon", theme: theme.compose(iconCss, css, 'icon'), classes: classes, variant: variant })))
                }));
            },
            content: function (toggleClosed) {
                function closeMenu() {
                    icache.set('focusNode', 'trigger');
                    toggleClosed();
                }
                var itemDisabled = properties().itemDisabled;
                return total === undefined && status === 'reading' ? (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", height: "auto", focusable: false, activeIndex: icache.getOrSet('activeIndex', strict ? 0 : -1), 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);
                                icache.set('selectedOption', 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*/