/// <reference path="../../js/knockout.d.ts" />
/// <reference path="../../js/jquery.d.ts" />
/// <reference path="../../js/jqueryui.d.ts" />
/// <reference path="../../js/actor-manager.ts" />
/// <reference path="../actor-selector/actor-selector.ts" />
/// <reference path="../../js/common.d.ts" />
/// <reference path="../../ajax-wrapper/ajax-action-wrapper.d.ts" />
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var AmeRedirectorUi;
(function (AmeRedirectorUi) {
    var AllKnownTriggers = {
        login: null,
        logout: null,
        registration: null,
        firstLogin: null
    };
    var _ = wsAmeLodash;
    var AbstractTriggerDictionary = /** @class */ (function () {
        function AbstractTriggerDictionary() {
        }
        return AbstractTriggerDictionary;
    }());
    var DefaultActorId = 'special:default';
    var defaultActor = {
        getDisplayName: function () {
            return 'Default';
        },
        getId: function () {
            return DefaultActorId;
        }
    };
    var Redirect = /** @class */ (function () {
        function Redirect(properties, actorProvider) {
            if (actorProvider === void 0) { actorProvider = null; }
            var _this = this;
            this.actorId = properties.actorId;
            this.trigger = properties.trigger;
            this.urlTemplate = ko.observable(properties.urlTemplate);
            this.menuTemplateId = ko.observable(properties.hasOwnProperty('menuTemplateId') ? properties.menuTemplateId : '');
            this.canToggleShortcodes = ko.pureComputed(function () {
                return (_this.menuTemplateId().trim() === '');
            });
            this.inputHasFocus = ko.observable(false);
            var internalShortcodesEnabled = ko.observable(properties.shortcodesEnabled);
            this.shortcodesEnabled = ko.computed({
                read: function () {
                    //All of the menu items use shortcodes to generate the admin page URL,
                    //so shortcodes must be enabled when a menu item is selected.
                    var menu = _this.menuTemplateId().trim();
                    if (menu !== '') {
                        return true;
                    }
                    return internalShortcodesEnabled();
                },
                write: function (value) {
                    if (!_this.canToggleShortcodes()) {
                        return;
                    }
                    internalShortcodesEnabled(value);
                },
                deferEvaluation: true
            });
            if (this.actorId === DefaultActorId) {
                this.actor = defaultActor;
            }
            else {
                var provider = actorProvider ? actorProvider : AmeActors;
                this.actor = provider.getActor(this.actorId);
            }
            this.actorTypeNoun = ko.pureComputed(function () {
                var prefix = _this.actorId.substring(0, _this.actorId.indexOf(':'));
                if (prefix === 'user') {
                    return 'user';
                }
                else if (prefix === 'role') {
                    return 'role';
                }
                return 'item';
            });
            this.urlDropdownEnabled = ko.pureComputed(function () {
                //If a menu item is already selected in the dropdown, the dropdown has to be enabled
                //to give the user the ability to select something else.
                var menu = _this.menuTemplateId().trim();
                if (menu !== '') {
                    return true;
                }
                //The dropdown only contains admin menu items, so it's only useful if the user
                //can access the admin dashboard after the trigger happens.
                //Note: This may need to change if we add other options to the dropdown.
                return (_this.trigger === 'login') || (_this.trigger === 'firstLogin');
            });
            Redirect.inputCounter++;
            this.inputElementId = 'ame-rui-unique-input-' + Redirect.inputCounter;
        }
        Redirect.prototype.toJs = function () {
            var result = {
                actorId: this.actorId,
                urlTemplate: this.urlTemplate().trim(),
                shortcodesEnabled: this.shortcodesEnabled(),
                trigger: this.trigger
            };
            var menu = this.menuTemplateId().trim();
            if (menu !== '') {
                result.menuTemplateId = menu;
            }
            return result;
        };
        Redirect.prototype.displayName = function () {
            if (this.actor.hasOwnProperty('userLogin')) {
                var user = this.actor;
                return user.userLogin;
            }
            else {
                return this.actor.getDisplayName();
            }
        };
        Redirect.inputCounter = 0;
        return Redirect;
    }());
    AmeRedirectorUi.Redirect = Redirect;
    var TriggerView = /** @class */ (function () {
        function TriggerView(trigger, supportsUserSettings, supportsRoleSettings) {
            if (supportsUserSettings === void 0) { supportsUserSettings = null; }
            if (supportsRoleSettings === void 0) { supportsRoleSettings = null; }
            var _this = this;
            this.users = ko.observableArray([]);
            this.roles = ko.observableArray([]);
            this.supportsUserSettings = true;
            this.supportsRoleSettings = true;
            if (supportsUserSettings !== null) {
                this.supportsUserSettings = supportsUserSettings;
            }
            if (supportsRoleSettings !== null) {
                this.supportsRoleSettings = supportsRoleSettings;
            }
            this.supportsActorSettings = ko.pureComputed(function () {
                return _this.supportsUserSettings || _this.supportsRoleSettings;
            });
            this.defaultRedirect = ko.observable(new Redirect({
                actorId: 'special:default',
                trigger: trigger,
                shortcodesEnabled: true,
                urlTemplate: ''
            }));
        }
        TriggerView.prototype.add = function (item) {
            var actorId = item.actorId;
            if (actorId === DefaultActorId) {
                this.defaultRedirect(item);
            }
            else if (actorId === 'special:super_admin') {
                this.roles.push(item);
            }
            else {
                var actorType = actorId.substring(0, actorId.indexOf(':'));
                switch (actorType) {
                    case 'user':
                        this.users.push(item);
                        break;
                    case 'role':
                        this.roles.push(item);
                        break;
                    default:
                        console.log('Unknown actor type for a trigger view: ' + actorType);
                }
            }
        };
        TriggerView.prototype.toArray = function () {
            var results = [];
            results.push.apply(results, this.users());
            results.push.apply(results, this.roles());
            //Include the default redirect only if it's not empty.
            var defaultRedirect = this.defaultRedirect();
            var url = defaultRedirect.urlTemplate().trim();
            if (url !== '') {
                results.push(defaultRedirect);
            }
            return results;
        };
        return TriggerView;
    }());
    var MenuCollection = /** @class */ (function () {
        function MenuCollection(usableMenuItems) {
            this.menusByTemplate = {};
            this.menusByTemplate = {};
            for (var i = 0; i < usableMenuItems.length; i++) {
                this.menusByTemplate[usableMenuItems[i].templateId] = usableMenuItems[i];
            }
        }
        MenuCollection.prototype.findSelectedMenu = function (redirect) {
            var templateId = redirect.menuTemplateId();
            if (templateId === '') {
                return null;
            }
            if (!this.menusByTemplate.hasOwnProperty(templateId)) {
                return null;
            }
            var menu = this.menusByTemplate[templateId];
            var url = redirect.urlTemplate();
            if (menu.url === url) {
                return menu;
            }
            return null;
        };
        return MenuCollection;
    }());
    var RedirectsByTrigger = /** @class */ (function (_super) {
        __extends(RedirectsByTrigger, _super);
        function RedirectsByTrigger() {
            var _this = _super.call(this) || this;
            _this.login = new TriggerView('login');
            _this.logout = new TriggerView('logout');
            _this.registration = new TriggerView('registration', false, false);
            _this.firstLogin = new TriggerView('firstLogin', false, true);
            return _this;
        }
        RedirectsByTrigger.fromArray = function (redirects) {
            var instance = new RedirectsByTrigger();
            var length = redirects.length;
            for (var i = 0; i < length; i++) {
                var item = redirects[i];
                if (instance.hasOwnProperty(item.trigger)) {
                    var view = instance[item.trigger];
                    view.add(item);
                }
            }
            return instance;
        };
        RedirectsByTrigger.prototype.toArray = function () {
            var results = [];
            for (var key in AllKnownTriggers) {
                if (this.hasOwnProperty(key)) {
                    var view = this[key];
                    results.push.apply(results, view.toArray());
                }
            }
            //Remove redirects that don't have a URL.
            results = results.filter(function (redirect) {
                var url = redirect.urlTemplate().trim();
                return ((typeof url) === 'string') && (url !== '');
            });
            return results;
        };
        return RedirectsByTrigger;
    }(AbstractTriggerDictionary));
    var RedirectUrlInputComponent = /** @class */ (function () {
        function RedirectUrlInputComponent(params) {
            var _this = this;
            this.redirect = ko.unwrap(params.redirect);
            this.menuItems = params.menuItems;
            this.displayValue = ko.computed({
                read: function () {
                    var menu = _this.menuItems.findSelectedMenu(_this.redirect);
                    if (menu) {
                        return menu.title;
                    }
                    else {
                        return _this.redirect.urlTemplate();
                    }
                },
                write: function (value) {
                    var menu = _this.menuItems.findSelectedMenu(_this.redirect);
                    if (menu !== null) {
                        //Can't manually edit the URL because a menu item is selected.
                        return;
                    }
                    _this.redirect.urlTemplate(value);
                }
            });
            this.isUrlReadonly = ko.pureComputed(function () {
                if (_this.menuItems.findSelectedMenu(_this.redirect) !== null) {
                    return true;
                }
                return null;
            });
        }
        return RedirectUrlInputComponent;
    }());
    AmeRedirectorUi.RedirectUrlInputComponent = RedirectUrlInputComponent;
    /**
     * Proxy class that automatically creates placeholders for missing actors.
     */
    var ActorProviderProxy = /** @class */ (function () {
        function ActorProviderProxy(realProvider) {
            this.provider = realProvider;
            this.placeholders = {};
        }
        ActorProviderProxy.prototype.getActor = function (actorId) {
            if (actorId === DefaultActorId) {
                return defaultActor;
            }
            var existingActor = this.provider.getActor(actorId);
            if (existingActor) {
                return existingActor;
            }
            else if (this.placeholders.hasOwnProperty(actorId)) {
                return this.placeholders[actorId];
            }
            //If the actor hasn't been loaded or created by now, that means it has been deleted
            //or it was invalid to begin with. Let's use a placeholder object to represent it.
            var missingActor;
            if (_.startsWith(actorId, 'user:')) {
                missingActor = new MissingUserPlaceholder(actorId);
            }
            else if (_.startsWith(actorId, 'role:')) {
                missingActor = new MissingRolePlaceholder(actorId);
            }
            else {
                missingActor = new MissingActorPlaceholder(actorId);
            }
            this.placeholders[actorId] = missingActor;
            return missingActor;
        };
        return ActorProviderProxy;
    }());
    var MinimalUser = /** @class */ (function (_super) {
        __extends(MinimalUser, _super);
        function MinimalUser() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        MinimalUser.createFromProperties = function (properties) {
            return new MinimalUser(properties.user_login, properties.display_name, {}, [], false);
        };
        return MinimalUser;
    }(AmeUser));
    AmeRedirectorUi.MinimalUser = MinimalUser;
    var MissingActorPlaceholder = /** @class */ (function () {
        function MissingActorPlaceholder(id, displayName) {
            if (displayName === void 0) { displayName = null; }
            this.actorId = id;
            if (displayName !== null) {
                this.displayName = displayName;
            }
            else {
                this.displayName = this.idWithoutPrefix(id);
            }
        }
        MissingActorPlaceholder.prototype.getDisplayName = function () {
            return this.displayName;
        };
        MissingActorPlaceholder.prototype.getId = function () {
            return this.actorId;
        };
        MissingActorPlaceholder.prototype.idWithoutPrefix = function (actorId) {
            var delimiterPos = actorId.indexOf(':');
            if (delimiterPos < 0) {
                return actorId;
            }
            return actorId.substring(delimiterPos + 1);
        };
        return MissingActorPlaceholder;
    }());
    var MissingRolePlaceholder = /** @class */ (function (_super) {
        __extends(MissingRolePlaceholder, _super);
        function MissingRolePlaceholder() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return MissingRolePlaceholder;
    }(MissingActorPlaceholder));
    var MissingUserPlaceholder = /** @class */ (function (_super) {
        __extends(MissingUserPlaceholder, _super);
        function MissingUserPlaceholder(actorId) {
            var _this = _super.call(this, actorId) || this;
            _this.isSuperAdmin = false;
            _this.userLogin = _this.idWithoutPrefix(actorId);
            return _this;
        }
        return MissingUserPlaceholder;
    }(MissingActorPlaceholder));
    var App = /** @class */ (function () {
        function App(settings) {
            var _this = this;
            this.isLoaded = ko.observable(false);
            this.availableTriggers = [
                { trigger: 'login', label: 'Login Redirect' },
                { trigger: 'logout', label: 'Logout Redirect' },
                { trigger: 'registration', label: 'Registration Redirect' },
                { trigger: 'firstLogin', label: 'First Login Redirect' }
            ];
            this.customUrlOption = {
                templateId: '',
                url: '',
                title: '[ Custom URL ]'
            };
            this.ignoreNextDropdownClick = null;
            this.userSelectionUi = 'dropdown';
            var self = this;
            this.actorProvider = new ActorProviderProxy(AmeActors);
            //Users need to be loaded before redirects because redirects use actor objects.
            var loadedUsers = settings.users.map(function (props) {
                var existingInstance = AmeActors.getUser(props.user_login);
                if (existingInstance) {
                    return existingInstance;
                }
                else {
                    var newUser = MinimalUser.createFromProperties(props);
                    AmeActors.addUsers([newUser]);
                    return newUser;
                }
            });
            loadedUsers.sort(function (a, b) {
                return a.userLogin.localeCompare(b.userLogin);
            });
            this.redirects = ko.observableArray(settings.redirects.map(function (props) { return new Redirect(props, _this.actorProvider); }));
            this.menuItems = new MenuCollection(settings.usableMenuItems);
            this.menuDropdownOptions = [this.customUrlOption].concat(settings.usableMenuItems);
            this.menuDropdownParent = ko.observable(null);
            this.selectedMenuDropdownItem = ko.computed({
                read: function () {
                    var currentRedirect = _this.menuDropdownParent();
                    if (currentRedirect === null) {
                        return _this.customUrlOption;
                    }
                    else {
                        //Find the option that matches this template ID and URL.
                        var foundMenu = _this.menuItems.findSelectedMenu(currentRedirect);
                        if (foundMenu === null) {
                            foundMenu = _this.customUrlOption;
                        }
                        return foundMenu;
                    }
                },
                write: function (newValue) {
                    var currentRedirect = _this.menuDropdownParent();
                    if (!currentRedirect) {
                        return; //Nothing to do!
                    }
                    if (!newValue) {
                        newValue = _this.customUrlOption;
                    }
                    currentRedirect.menuTemplateId(newValue.templateId);
                    if (newValue.templateId !== '') {
                        currentRedirect.urlTemplate(newValue.url);
                    }
                },
                owner: self,
                deferEvaluation: true
            });
            this.menuDropdown = jQuery('#ame-rui-menu-items');
            //Hide the dropdown when it loses focus.
            this.menuDropdown.on('blur', function () {
                _this.closeMenuDropdown();
            });
            this.menuDropdown.on('keydown', function (event) {
                //Also hide the dropdown if the user presses Esc.
                if (event.which === 27) {
                    _this.closeMenuDropdown(true);
                }
                else if (event.which === 13) {
                    //Close the dropdown when the user presses Enter.
                    //Since we currently update the redirect on every change, there's no difference between
                    //this and pressing Esc.
                    _this.closeMenuDropdown(true);
                }
            });
            //Close the dropdown when the user selects an option by clicking it.
            this.menuDropdown.on('click', 'option', function () {
                _this.closeMenuDropdown();
            });
            //this.addTestData();
            this.byTrigger = ko.observable(RedirectsByTrigger.fromArray(this.redirects()));
            //Reselect the previous trigger, or just the first trigger.
            this.selectedTrigger = ko.observable(settings.selectedTrigger ? settings.selectedTrigger : this.availableTriggers[0].trigger);
            this.currentTriggerView = ko.pureComputed(function () {
                var trigger = _this.selectedTrigger();
                var mapping = _this.byTrigger();
                if (mapping.hasOwnProperty(trigger) && (mapping[trigger] instanceof TriggerView)) {
                    return mapping[trigger];
                }
                else {
                    return mapping.login;
                }
            });
            this.addableRoles = ko.pureComputed(function () {
                var allRoles = _.values(AmeActors.getRoles());
                var usedRoles = _.map(_this.currentTriggerView().roles(), function (redirect) {
                    return redirect.actor;
                });
                return _.difference(allRoles, usedRoles);
            });
            this.selectedRoleToAdd = ko.observable(void 0);
            this.roleSelectorHasFocus = ko.observable(false);
            this.addableUsers = ko.pureComputed(function () {
                var usedUsers = _.map(_this.currentTriggerView().users(), function (redirect) {
                    return redirect.actor;
                });
                return _.difference(loadedUsers, usedUsers);
            });
            this.selectedUserToAdd = ko.observable(void 0);
            this.userSelectorHasFocus = ko.observable(false);
            this.selectedRoleToAdd.subscribe(function (newSelection) {
                _this.addSelectedActorTo(newSelection, _this.currentTriggerView().roles);
                _this.roleSelectorHasFocus(false);
                _this.selectedRoleToAdd(void 0);
            });
            this.selectedUserToAdd.subscribe(function (newSelection) {
                _this.addSelectedActorTo(newSelection, _this.currentTriggerView().users);
                _this.userSelectorHasFocus(false);
                _this.selectedUserToAdd(void 0);
            });
            this.userLoginQuery = ko.observable('');
            this.addUserButtonEnabled = ko.pureComputed(function () {
                return (_this.userLoginQuery().trim() !== '');
            });
            if (settings.hasMoreUsers) {
                this.userSelectionUi = 'search';
            }
            this.isSaving = ko.observable(false);
            this.settingsData = ko.observable('');
            this.isLoaded(true);
        }
        App.prototype.getSettings = function () {
            return {
                redirects: this.byTrigger().toArray().map(function (redirect) { return redirect.toJs(); })
            };
        };
        App.prototype.onDropdownTrigger = function (event) {
            //Note: There probably is some jQuery feature or library that makes dropdowns easier,
            //but I already did this the hard way.
            var $input = jQuery(event.target).closest('.ame-rui-url-template,ame-redirect-url-input').find('input').first();
            var $node = $input.closest('.ame-rui-redirect');
            if ($node.length < 1) {
                return;
            }
            var redirect = ko.dataFor($node.get(0));
            if (!(redirect instanceof AmeRedirectorUi.Redirect)) {
                return;
            }
            //Clicking the same trigger a second time closes the dropdown.
            if (event.type === 'mousedown') {
                var isSameTrigger = this.menuDropdown.is(':visible') && (this.menuDropdownParent() === redirect);
                if (isSameTrigger) {
                    //The dropdown will be automatically closed by its "blur" event handler,
                    //but we need to ignore the next click event on this element.
                    this.ignoreNextDropdownClick = event.target;
                }
                else {
                    this.ignoreNextDropdownClick = null;
                }
                return;
            }
            if ((event.type === 'click') && (event.target === this.ignoreNextDropdownClick)) {
                return;
            }
            //Move the drop-down near the input box.
            this.menuDropdown
                .css({
                position: 'absolute',
                zIndex: 100 //The dropdown should be displayed above other elements. This may not be required.
            })
                .show()
                .outerWidth(Math.max($input.outerWidth(), 100))
                .position({
                my: 'right top',
                at: 'right bottom',
                of: $input
            });
            //Move focus to the dropdown.
            var $select = this.menuDropdown;
            if (!this.menuDropdown.is('select, input')) {
                $select = this.menuDropdown.find('select, input').first();
            }
            $select.trigger('focus');
            //Select the current option and scroll it into view. It looks like the browser will automatically
            //scroll to the selected option, but only if the select element is already visible, so we need to
            //do this *after* we show the dropdown.
            this.menuDropdownParent(redirect);
        };
        App.prototype.closeMenuDropdown = function (moveFocusToInput) {
            if (moveFocusToInput === void 0) { moveFocusToInput = false; }
            var currentRedirect = this.menuDropdownParent();
            this.menuDropdown.hide();
            this.menuDropdownParent(null);
            //Refocus on the URL input after closing the dropdown.
            if (moveFocusToInput && currentRedirect) {
                currentRedirect.inputHasFocus(true);
            }
        };
        App.prototype.addSelectedActorTo = function (actor, list) {
            //The list includes a caption item that is displayed when nothing is selected.
            //The value of that option is supposed to be undefined.
            if ((typeof actor === 'undefined') || (actor === null) || !this.currentTriggerView()) {
                return;
            }
            //Add a redirect for the selected role.
            var newRedirect = new Redirect({
                actorId: actor.getId(),
                shortcodesEnabled: true,
                urlTemplate: '',
                trigger: this.selectedTrigger()
            }, this.actorProvider);
            list.push(newRedirect);
            newRedirect.inputHasFocus(true);
        };
        App.prototype.addEnteredUserLogin = function () {
            var userLogin = this.userLoginQuery().trim();
            if (userLogin === '') {
                return;
            }
            var actorId = 'user:' + userLogin;
            if (!AmeActors.actorExists(actorId)) {
                if (console && console.warn) {
                    console.warn('User "' + userLogin + '" has not been initialized. Creating a minimal actor now.');
                }
                AmeActors.addUsers([
                    MinimalUser.createFromProperties({
                        user_login: userLogin,
                        display_name: userLogin
                    })
                ]);
            }
            //Only add each user once.
            var alreadyAdded = _.some(this.currentTriggerView().users(), function (redirect) {
                return redirect.actorId === actorId;
            });
            if (alreadyAdded) {
                alert('Error: Duplicate entry. User "' + userLogin + '" has already been added.');
                return;
            }
            var newRedirect = new Redirect({
                actorId: actorId,
                shortcodesEnabled: true,
                urlTemplate: '',
                trigger: this.selectedTrigger()
            }, this.actorProvider);
            this.currentTriggerView().users.push(newRedirect);
            this.userLoginQuery('');
        };
        App.prototype.filterUserAutocompleteResults = function (results) {
            //Filter out users that are already in the current list.
            var usedLogins = _.indexBy(this.currentTriggerView().users(), function (redirect) {
                return redirect.actor.userLogin;
            });
            return _.filter(results, function (props) {
                return !(usedLogins.hasOwnProperty(props.user_login));
            });
        };
        App.prototype.isMissingActor = function (actor) {
            return (actor instanceof MissingActorPlaceholder);
        };
        App.prototype.saveChanges = function () {
            this.isSaving(true);
            this.settingsData(ko.toJSON(this.getSettings()));
            return true;
        };
        App.prototype.addTestData = function () {
            //Add some test data.
            this.redirects.push(new Redirect({
                actorId: 'role:editor',
                urlTemplate: '[wp-admin]edit.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: 'role:author',
                urlTemplate: '[wp-admin]profile.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: 'user:admin',
                urlTemplate: '[wp-admin]index.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: 'role:contributor',
                urlTemplate: '[wp-admin]index.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: 'role:nonexistent',
                urlTemplate: '[wp-admin]options-general.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: 'user:notarealuser',
                urlTemplate: '[wp-admin]index.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: DefaultActorId,
                urlTemplate: '[wp-admin]index.php?this-is-the-default=yep',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
            this.redirects.push(new Redirect({
                actorId: 'role:administrator',
                urlTemplate: '[wp-admin]options-general.php',
                trigger: 'login',
                shortcodesEnabled: true
            }, this.actorProvider));
        };
        return App;
    }());
    AmeRedirectorUi.App = App;
})(AmeRedirectorUi || (AmeRedirectorUi = {}));
jQuery(function ($) {
    ko.components.register('ame-redirect-url-input', {
        viewModel: AmeRedirectorUi.RedirectUrlInputComponent,
        template: { element: 'ame-redirect-url-component' }
    });
    //The user autocomplete feature is implemented as a custom binding only because that makes it easier
    //to correctly initialise it when Knockout changes the DOM. The binding is not intended to be reusable.
    ko.bindingHandlers.ameRuiUserAutocomplete = {
        init: function (element, valueAccessor) {
            var options = ko.unwrap(valueAccessor());
            options = wsAmeLodash.defaults(options, {
                filter: function (suggestions) {
                    return suggestions;
                }
            });
            jQuery(element).autocomplete({
                minLength: 2,
                source: function (request, response) {
                    var action = AjawV1.getAction('ws-ame-rui-search-users');
                    action.get({ term: request.term }, function (results) {
                        //Filter received users.
                        if (options.filter) {
                            results = options.filter(results);
                        }
                        response(results);
                    }, function (error) {
                        response([]);
                        if (console && console.error) {
                            console.error(error);
                        }
                    });
                },
                select: function (unusedEvent, ui) {
                    var props = ui.item;
                    var existingUser = AmeActors.getUser(props.user_login);
                    if (existingUser === null) {
                        AmeActors.addUsers([AmeRedirectorUi.MinimalUser.createFromProperties(props)]);
                    }
                },
                classes: {
                    'ui-autocomplete': 'ame-rui-found-users'
                }
            });
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                jQuery(element).autocomplete('destroy');
            });
        }
    };
    var $container = $('#ame-redirector-ui-root');
    var ameRedirectorApp = new AmeRedirectorUi.App(wsAmeRedirectorSettings);
    ko.applyBindings(ameRedirectorApp, $container.get(0));
    //Open the menu dropdown when the user clicks the trigger icon or presses
    //the down arrow key in the redirect input field.
    $container.on('mousedown click', '.ame-rui-url-dropdown-trigger', function (event) {
        ameRedirectorApp.onDropdownTrigger(event);
    });
    /*
    Releasing the "down" key only opens the dropdown if the key was pressed in the same input.
    This is to avoid a confusing situation where the user selects a role from the "add a role"
    dropdown using arrow keys and then the menu dropdown immediately shows up because the focus
    moved to the redirect input before the user could release the key.
    */
    var redirectInputSelector = '.ame-rui-url-template input[type=text].ame-rui-has-url-dropdown';
    var lastDownArrowTarget = null;
    $container.on('focus', redirectInputSelector, function () {
        lastDownArrowTarget = null;
    });
    $container.on('keydown', redirectInputSelector, function (event) {
        //Ignore repeated "keydown" events. These will happen even if the key was originally
        //pressed in a different element.
        if ((typeof event.originalEvent['repeat'] !== 'undefined') && (event.originalEvent['repeat'] === true)) {
            return;
        }
        if (event.which === 40) {
            lastDownArrowTarget = event.target;
        }
    });
    $container.on('keyup', redirectInputSelector, function (event) {
        if ((event.which === 40) && (event.target === lastDownArrowTarget)) {
            ameRedirectorApp.onDropdownTrigger(event);
        }
    });
});
//# sourceMappingURL=redirector-ui.js.map