/** @class */
jscape.domain.TriggerActionsController = jscape.view.WizardDialog.Page.extend(
    /** @lends {jscape.domain.TriggerActionsController.prototype} */
{
    items: null,
    actions: null,
    functions: null,
    eventProperties: null,

    /** @constructor */
    initialize: function(container) {
        this.view = new jscape.domain.TriggerActionsView(container);

        this.addController = new jscape.domain.AddTriggerActionController();
        this.editController = new jscape.domain.EditTriggerActionController();
        this.deleteController = new jscape.domain.DeleteTriggerActionController();
    },

    start: function(managementService, domainName, triggerContext, actionContexts) {
        this.managementService = managementService;
        this.domainName = domainName;
        this.actions = triggerContext.actions;
        this.functions = triggerContext.functions;
        this.variables = [];
        this.items = $.map(actionContexts || [], $.proxy(function(entry) { return this._rowDataFor(entry); }, this));

        this.view.setItems(this.items);
        this.view.show(this);
    },

    setVariables: function(values) {
        this.variables = values || [];
    },

    /** @overrde */
    pause: function() {
        this.view.hide();
    },

    /** @overrde */
    resume: function() {
        this.view.show(this);
    },

    createActionContexts: function() {
        return $.map(this.items, $.proxy(function(entry) { return this._actionContextOf(entry); }, this));
    },

    onActionUp: function (item) {
        var index = $.inArray(item, this.items);
        if (index != -1) {
            this.items.splice(index - 1, 2, this.items[index], this.items[index - 1]);
            this.view.setItems(this.items);
            this.view.selectItem(item);
        }
    },

    onActionDown: function (item) {
        var index = $.inArray(item, this.items);
        if (index != -1 && index < this.items.length - 1) {
            this.items.splice(index, 2, this.items[index + 1], this.items[index]);
            this.view.setItems(this.items);
            this.view.selectItem(item);
        }
    },

    onAddAction: function () {
        this.addController.start(this.managementService, this.domainName, this.actions, this.functions, this.variables)
                .then($.proxy(function(actionContext) { return this._rowDataFor(actionContext); }, this))
                .done($.proxy(this._actionAdded, this));
    },

    onEditAction: function (item) {
        var index = $.inArray(item, this.items);
        if (index != -1) {
            var actionContext = this._actionContextOf(item);
            this.editController.start(this.managementService, this.domainName, this.functions, this.variables, actionContext, item.name)
                    .then($.proxy(function(actionContext) { return this._rowDataFor(actionContext); }, this))
                    .done($.proxy(this._actionEdited, this, index));
        }
    },

    onDeleteAction: function (items) {
        this.deleteController.start(items)
                .done($.proxy(this._actionDeleted, this, items));
    },

    _actionAdded: function(item) {
        this.items.push(item);
        this.view.setItems(this.items);
        this.view.selectItem(item);
    },

    _actionEdited: function(index, item) {
        this.items[index] = item;
        this.view.setItems(this.items);
        this.view.selectItem(item);
    },

    _actionDeleted: function (items) {
        var index = -1;
        while (items.length) {
            index = $.inArray(items.pop(), this.items);
            this.items.splice(index, 1);
        }
        this.view.setItems(this.items);

        if (this.items.length) {
            index = Math.max(0, Math.min(index, this.items.length - 1));
            this.view.selectItem(this.items[index]);
        }
    },

    _actionContextOf: function(rowData) {
        var context = $.extend(true, {}, rowData);
        delete context.name;
        delete context.description;
        return context;
    },

    _rowDataFor: function(actionContext) {
        for (var i = 0; i < this.actions.length; i++) {
            var entry = this.actions[i];
            if (entry.actionClass === actionContext.actionClass) {
                return $.extend(true, {}, actionContext, {name: entry.name, description: entry.description, notes: entry.notes});
            }
        }
        return null;
    },

    _setupView: function() {
        this.view.setItems(this.item)
    }
});

/** @class */
jscape.domain.TriggerActionsView = Class.extend(
    /** @lends {jscape.domain.TriggerActionsView.prototype} */
{
    selection: null,

    /** @constructor */
    initialize: function(container) {
        this.selection = [];

        this.fieldset = $("fieldset[name=triggeractionsfields]", container);

        this.data = $("table[role=grid][aria-label=triggeractions]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            remoteSort: false,
            ctrlSelect: true,
            onSelect: $.proxy(this._adjustRowSelection, this),
            onUnselect: $.proxy(this._adjustRowSelection, this),
            onLoadSuccess: $.proxy(this._adjustRowSelection, this),
            onDblClickRow: $.proxy(this._onClick$EditButton, this),
            columns: [[
                {field: "name", title: $("thead th:nth-child(1)", this.data).text(), width: 100},
                {field: "description", title: $("thead th:nth-child(2)", this.data).text(), width: 200},
                {field: "notes", title: $("thead th:nth-child(3)", this.data).text(), width: 200}
            ]]
        });

        this.moveUpButton = $("a[role=button][name=moveup]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$MoveUpButton, this)});
        this.moveDownButton = $("a[role=button][name=movedown]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$MoveDownButton, this)});
        this.addButton = $("a[role=button][name=add]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$AddButton, this)});
        this.editButton = $("a[role=button][name=edit]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$EditButton, this)});
        this.deleteButton = $("a[role=button][name=delete]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$DeleteButton, this)});
    },

    getItems: function() {
        return this.data.datagrid("getRows");
    },

    setItems: function(values) {
        this.data.datagrid("loading").datagrid("loadData", values).datagrid("loaded");
    },

    selectItem: function(value) {
        this.data.datagrid("selectRow", this.data.datagrid("getRowIndex", value));
    },

    show: function(listener) {
        this.listener = listener || jscape.domain.TriggerActionsView.LISTENER;
        this.fieldset.show();
        this.data.datagrid("resize").datagrid("fitColumns");
    },

    hide: function() {
        this.fieldset.hide();
    },

    _onClick$MoveUpButton: function() {
        this.listener.onActionUp(this.selection[0]);
    },

    _onClick$MoveDownButton: function() {
        this.listener.onActionDown(this.selection[0]);
    },

    _onClick$AddButton: function() {
        this.listener.onAddAction();
    },

    _onClick$EditButton: function() {
        this.listener.onEditAction(this.selection[0]);
    },

    _onClick$DeleteButton: function() {
        this.listener.onDeleteAction(this.selection);
    },

    _adjustRowSelection: function() {
        this.selection = this.data.datagrid("getSelections");
        this._adjustButtonsState();
    },

    _adjustButtonsState: function() {
        var index = this.selection.length == 1 ? this.data.datagrid("getRowIndex", this.selection[0]) : -1;
        var count = this.data.datagrid("getRows").length;

        this.moveUpButton.linkbutton(index > 0 && index <= count - 1 ? "enable" : "disable");
        this.moveDownButton.linkbutton(index >= 0 && index < count - 1 ? "enable" : "disable");
        this.editButton.linkbutton(this.selection.length == 1 ? "enable" : "disable");
        this.deleteButton.linkbutton(this.selection.length != 0 ? "enable" : "disable");
    }
});
jscape.domain.TriggerActionsView.LISTENER = {
    onActionUp: $.noop,
    onActionDown: $.noop,
    onAddAction: $.noop,
    onEditAction: $.noop,
    onDeleteAction: $.noop
};

/** @class */
jscape.domain.BaseTriggerActionController = Class.extend(
    /** @lends {jscape.domain.BaseTriggerActionController.prototype} */
{
    controllers: null,
    functions: null,
    variables: null,
    actionClass: null,
    deferred: null,

    /** @constructor */
    initialize: function() {
        this.variableController = new jscape.VariableController();
        this.functionController = new jscape.FunctionController();
    },

    onAddVariable: function(input) {
        this.variableController.start(input, this.variables || []);
    },

    onAddFunction: function(input) {
        this.functionController.start(input, this.functions);
    },

    onSubmit: function (dialog) {
        $.each(this.controllers, function(_, controller) { controller.onPause(); });

        this.managementService.testTriggerActionContext(this.domainName, this.actionContext)
                .done($.proxy(function (valid) {
                          if (valid) {
                              $.each(this.controllers, $.proxy(function(_, controller) { controller.onStop(dialog); }, this));
                              dialog.destroy();
                              this.deferred.resolve(this.actionContext);
                              this.deferred = null;
                          } else {
                              this._showActionContextError();
                              $.each(this.controllers, function(_, controller) { controller.onResume(); });
                          }
                      }, this));
    },

    onCancel: function(dialog) {
        dialog.destroy();
        this.deferred.reject();
        this.deferred = null;
    },

    _createController: function(type) {
        type = (type || "").toLowerCase();
        if (type == "integer") {
            return new jscape.domain.NumberPropertyController();
        } else if (type == "boolean" || type == "logaction") {
            return new jscape.domain.BooleanPropertyController();
        } else if (type == "string" || type == "memo" || type == "password") {
            return new jscape.domain.StringPropertyController();
        } else if (type == "choice") {
            return new jscape.domain.ComboboxPropertyController();
        } else if (type == "path") {
            return new jscape.domain.PathPropertyController(new jscape.domain.PathPropertyController.PathProvider());
        } else if (type == "file") {
            return new jscape.domain.PathPropertyController(new jscape.domain.PathPropertyController.FileProvider());
        } else if (type == "directory") {
            return new jscape.domain.PathPropertyController(new jscape.domain.PathPropertyController.DirectoryProvider());
        } else if (type == "account") {
            return new jscape.domain.DisableUsersPropertyController();
        } else if (type == "hostkey") {
            return new jscape.domain.HostKeysPropertyController();
        } else if (type == "pgppublickey") {
            return new jscape.domain.PgpPublicKeysPropertyController();
        } else if (type == "pgpsecretkey") {
            return new jscape.domain.PgpSecretKeysPropertyController();
        } else if (type == "partner") {
            return new jscape.domain.TradingPartnersPropertyController();
        } else if (type == "directorymonitor") {
            return new jscape.domain.DirectoryMonitorsPropertyController();
        } else if (type == "owner") {
            return new jscape.domain.OwnerPropertyController();
        } else if (type == "urlbranding") {
            return new jscape.domain.UrlBrandingPropertyController();
        } else if (type == "amazonsnstopic") {
            return new jscape.domain.AmazonSnsTopicPropertyController();
        }
        throw "Unsupported field: " + type;
    },

    _showActionContextError: function() {
        $.messager.alert(window.R.string.APPLICATION_ERROR_TITLE,
                         window.R.string.TRIGGERS_ERROR_ACTION_TEST_FAILED,
                         "error");

    }
});

/** @class */
jscape.domain.AddTriggerActionController = jscape.domain.BaseTriggerActionController.extend(
    /** @lends {jscape.domain.BaseTriggerActionController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
    },

    /** @override */
    start: function (managementService, domainName, types, functions, variables) {
        this.managementService = managementService;
        this.domainName = domainName;
        this.functions = functions || [];
        this.variables = variables || [];
        this.deferred = $.Deferred();

        this._selectActionType(types)
                .then($.proxy(function (action) {
                          this.actionName = action.name;
                          this.actionClass = action.actionClass;
                          this.actionContext = new jscape.ActionContext(this.actionClass);

                          return this.managementService.getTriggerAction(this.domainName, this.actionClass);
                      }, this))
                .done($.proxy(function (properties) {
                          this._createActionDialog(properties).show(this);
                      }, this))
                .fail($.proxy(function () {
                          this.deferred.reject();
                          this.deferred = null;
                      }, this));

        return this.deferred.promise();
    },

    _selectActionType: function (types) {
        var deferred = $.Deferred();
        var dialog = new jscape.domain.TriggerActionTypeDialog();
        dialog.setActions(types);
        dialog.show({
            onSubmit: $.proxy(function(d) { var action = d.getAction(); d.destroy(); deferred.resolve(action); }, this),
            onCancel: $.proxy(function(d) { d.destroy(); deferred.reject(); }, this)
        });
        return deferred.promise();
    },

    _createActionDialog: function (properties) {
        this.controllers = [];

        var dialog = new jscape.domain.AddTriggerActionDialog();
        dialog.setActionName(this.actionName);
        var controller;

        $.each(properties, $.proxy(function(_, property) {
            controller = this._createController(property.field.type);
            controller.onCreate(this.domainName, property, this.actionContext);
            this.controllers.push(controller);
            controller.onStart(dialog);
            controller.onResume();
        }, this));

        controller = new jscape.domain.ActionContextNotesController();
        controller.onCreate(this.domainName, null, this.actionContext);
        this.controllers.push(controller);
        controller.onStart(dialog);
        controller.onResume();

        dialog.finish();

        return dialog;
    }
});

/** @class */
jscape.domain.EditTriggerActionController = jscape.domain.BaseTriggerActionController.extend(
    /** @lends {jscape.domain.EditTriggerActionController.prototype} */
{
    /** @override */
    start: function (managementService, domainName, functions, variables, actionContext, actionName) {
        this.managementService = managementService;
        this.domainName = domainName;
        this.functions = functions || [];
        this.variables = variables || [];
        this.actionContext = actionContext;
        this.actionName = actionName;
        this.actionClass = actionContext.actionClass;
        this.deferred = $.Deferred();

        this.managementService.getTriggerAction(this.domainName, this.actionClass)
                .done($.proxy(function (properties) {
                          this._createActionDialog(properties).show(this);
                      }, this))
                .fail($.proxy(function () {
                          this.deferred.reject();
                          this.deferred = null;
                      }, this));

        return this.deferred.promise();
    },

    _createActionDialog: function (properties) {
        this.controllers = [];

        var dialog = new jscape.domain.EditTriggerActionDialog();
        dialog.setActionName(this.actionName);
        var controller;

        $.each(properties, $.proxy(function(_, property) {
            controller = this._createController(property.field.type);
            controller.onCreate(this.domainName, property, this.actionContext);
            this.controllers.push(controller);
            controller.onStart(dialog);
            controller.onResume();
        }, this));

        controller = new jscape.domain.ActionContextNotesController();
        controller.onCreate(this.domainName, null, this.actionContext);
        this.controllers.push(controller);
        controller.onStart(dialog);
        controller.onResume();

        dialog.finish();

        return dialog;
    }
});

/** @class */
jscape.domain.TriggerActionTypeDialog = Class.extend(
    /** @lends {jscape.domain.TriggerActionTypeDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-triggers-actiontype").clone().attr("id", "");
        this.dialog.dialog({
            width: 530, height: "auto",
            modal: true, resizable: false, closable: true, closed: true,
            buttons: [
                {text: window.R.string.DIALOG_BUTTON_OK || "Ok", handler: $.proxy(this._onSubmit, this)},
                {text: window.R.string.DIALOG_BUTTON_CANCEL || "Cancel", handler: $.proxy(this._onCancel, this)}
            ],
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this)
        }).show();

        this.fieldset = $("fieldset[name=triggeractiontypefields]", this.dialog);

        this.action = $("select[name=action]", this.fieldset).combobox({
            required: true,
            limitToList: true,
            width: "60%",
            textField: "name",
            valueField: "actionClass",
            formatter: function(row) { return '<span title="' + String(row.description || "").escapeXml() + '">' + String(row.name || "").escapeXml() + '</span>'; },
            onChange: $.proxy(this._adjustActionHelp, this)
        });
        this.action.combobox("textbox").on("focus", function() { $(this).select(); });

        this.actionHelp = $("#trigger-action-help", this.fieldset)
                .tooltip({position: "bottom", showDelay: 200, onShow: function() {
                    $(this).tooltip("tip").addClass("tooltip-tip-black");
                    $(this).tooltip("reposition");
                }});
    },

    getAction: function() {
        var value = this.action.combobox("getValue");
        var actions = $.grep(this.action.combobox("getData"), function(action) { return action.actionClass == value; });
        return actions.length ? actions[0] : null;
    },

    setActions: function(values) {
        this.action.combobox("loadData", values);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this._adjustActionHelp();
        this.action.combobox("textbox").focus();
    },

    hide: function () {
        if (!this._closed()) {
            this.closing = true;
            this.dialog.dialog("close");
            this.fieldset.form("disableValidation");
            this.closing = false;
        }
    },

    destroy: function() {
        this.dialog.dialog("destroy");
    },

    _onSubmit: function () {
        if (this.fieldset.form("validate")) {
            this.hide();
            this.listener.onSubmit(this);
        }
    },

    _onCancel: function () {
        this.hide();
        this.listener.onCancel(this);
    },

    _closed: function () {
        return !!this.dialog.dialog("options").closed;
    },

    _adjustActionHelp: function () {
        var action = this.getAction();
        var content = action ? "<div class=\"tooltip-title\"><code>" + action.name + "</code></div>" + action.description : "";
        this.actionHelp.tooltip("update", content);
    }
});

/** @class */
jscape.domain.DeleteTriggerActionController = Class.extend(
    /** @lends {jscape.domain.DeleteTriggerActionController.prototype} */
{
    start: function(actions) {
        var text = $.map(actions, function(action) { return action.name; }).join(", ");
        return jscape.ConfirmDialog.confirm(window.R.string.TRIGGERS_CONFIRM_DELETE_ACTION_TITLE,
                                            window.R.string.TRIGGERS_CONFIRM_DELETE_ACTION_MESSAGE.supplant({0: text}));
    }
});

/** @class */
jscape.domain.TriggerActionDialog = Class.extend(
    /** @lends {jscape.domain.TriggerActionDialog.prototype} */
{
    FIELDSET_CLASSES: ["small", "large", "x-large", "xx-large", "xxx-large"],

    currentInput: null,
    views: null,

    /** @constructor */
    initialize: function(dialog) {
        this.views = [];

        this.dialog = dialog.clone().attr("id", $.now().toString(36));
        this.dialog.dialog({
            width: "75%", height: "auto",
            modal: true, resizable: true, closable: true, closed: true,
            buttons: [
                {text: window.R.string.DIALOG_BUTTON_OK || "Ok", handler: $.proxy(this._onSubmit, this)},
                {text: window.R.string.DIALOG_BUTTON_CANCEL || "Cancel", handler: $.proxy(this._onCancel, this)}
            ],
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this),
            onResize: $.proxy(this._onResize$Dialog, this)
        }).show();

        this.title = this.dialog.dialog("header").text() || "";

        this.fieldset = $("fieldset[name=triggeractionfields]", this.dialog);
        this.tabs = $("div[role=tablist]", this.fieldset).tabs({plain: true, width: "auto", height: 350});

        this.parametersFieldset = $("fieldset[name=parametersfields]", this.fieldset);
        this.advancedFieldset = $("fieldset[name=advancedparametersfields]", this.fieldset);

        this.variablesButton = $("a[role=button][name=addvariable]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$VariablesButton, this)});
        this.functionsButtons = $("a[role=button][name=addfunction]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$FunctionsButtons, this)});
    },

    setActionName: function(value) {
        this.dialog.dialog("setTitle", this.title.supplant({0: value || ""}));
    },

    addFormField: function(html, group) {
        if (group) {
            group = String(group).escapeXml();
            this._findGroup(group, this.parametersFieldset).append(html);
        } else {
            this.parametersFieldset.append(html);
        }
    },

    addAdvancedField: function(html, group) {
        if (group) {
            group = String(group).escapeXml();
            this._findGroup(group, this.advancedFieldset).append(html);
        } else {
            this.advancedFieldset.append(html);
        }
    },

    _findGroup: function(name, parent) {
        var t = parent.find("fieldset[name=" + name + "]");
        if (t.length) {
            return t;
        }
        var fs = $("<div><fieldset name='{name}'><legend>{name}</legend></fieldset></div>".supplant({name: name}));
        var groups = parent.find("fieldset");
        if (groups.length) {
            fs.insertAfter(groups.parent().last());
        } else {
            var c = parent.children();
            if (c.length) {
                fs.insertBefore(c.first());
            } else {
                parent.append(fs);
            }
        }
        return parent.find("fieldset[name=" + name + "]");
    },

    finish: function() {
        this.parametersFieldset.focusin($.proxy(this._onForm$FocusIn, this));
        this.advancedFieldset.focusin($.proxy(this._onForm$FocusIn, this));
        this.tabs.tabs({onSelect: function (_, index) { $(this).tabs("getTab", index).find("fieldset").trigger("focusin"); }});
    },

    container: function() {
        return this.fieldset;
    },

    register: function(view) {
        this.views.push(view);
    },

    unregister: function(view) {
        for (var i = 0; i < this.views.length; ++i) {
            if (view == this.views[i]) {
                this.views.splice(i--, 1);
            }
        }
    },

    show: function (listener) {
        this.listener = listener;
        this.currentInput = null;
        this.dialog.dialog("center").dialog("open").dialog("resize");
        this.fieldset.form("validate");
        this.fieldset.find("input:not(:disabled):first").focus();
    },

    hide: function () {
        if (!this._closed()) {
            this.closing = true;
            this.dialog.dialog("close");
            this.fieldset.form("disableValidation");
            this.closing = false;
        }
        this.currentInput = null;
    },

    destroy: function() {
        this.hide();
        this.currentInput = null;
        this.dialog.dialog("destroy");
    },

    _onResize$Dialog: function() {
        this._inspect(this.parametersFieldset);
        this._inspect(this.advancedFieldset);
    },

    _inspect: function(fieldset) {
        if (!fieldset || !fieldset.is(":visible") || $.data(fieldset[0], "__inspected__")) {
            return;
        }
        for (var i = 0; i < this.views.length; ++i) {
            if (!this.views[i].collide()) {
                continue;
            }

            var index = this._indexOfClass(fieldset, this.FIELDSET_CLASSES);
            if (index >= 0 && (index + 1) < this.FIELDSET_CLASSES.length - 1) {
                fieldset.addClass(this.FIELDSET_CLASSES[index + 1]);
                fieldset.removeClass(this.FIELDSET_CLASSES[index]);
                --i;
            } else {
                break;
            }
        }
        $.data(fieldset[0], "__inspected__", true);
    },

    _indexOfClass: function(fieldset, classes) {
        for (var i = 0; i < classes.length; ++i) {
            if (fieldset.hasClass(classes[i])) {
                return i;
            }
        }
        return -1;
    },

    _onClick$VariablesButton: function() {
        if (this.currentInput && this.currentInput.is(":not(:disabled)")) {
            this.listener.onAddVariable(this.currentInput);
        }
    },

    _onClick$FunctionsButtons: function() {
        if (this.currentInput && this.currentInput.is(":not(:disabled)")) {
            this.listener.onAddFunction(this.currentInput);
        }
    },

    _onForm$FocusIn: function (e) {
        var t = $(e.target);
        if (t.is("input[type=text]:visible:not([readonly])") || t.is("textarea:visible")) {
            this.variablesButton.linkbutton("enable");
            this.functionsButtons.linkbutton("enable");
            this.currentInput = t;
        } else {
            this.variablesButton.linkbutton("disable");
            this.functionsButtons.linkbutton("disable");
            this.currentInput = null;
            if (t.is("fieldset")) {
                this._inspect(t);
            }
        }
    },

    _onSubmit: function () {
        if (this.fieldset.form("validate")) {
            this.listener.onSubmit(this);
        }
    },

    _onCancel: function () {
        this.hide();
        this.listener.onCancel(this);
    },

    _closed: function () {
        return !!this.dialog.dialog("options").closed;
    }
});
jscape.domain.TriggerActionDialog.LISTENER = {
    onAddVariable: $.noop,
    onAddFunction: $.noop
};

/** @class */
jscape.domain.AddTriggerActionDialog = jscape.domain.TriggerActionDialog.extend(
    /** @lends {jscape.domain.AddTriggerActionDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-triggers-addaction"));
    }
});

/** @class */
jscape.domain.EditTriggerActionDialog = jscape.domain.TriggerActionDialog.extend(
    /** @lends {jscape.domain.EditTriggerActionDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-triggers-editaction"));
    }
});

/** @class */
jscape.domain.PropertyController = Class.extend(
    /** @lends {jscape.domain.PropertyController.prototype} */
{
    property: null,
    view: null,

    onCreate: function(domainName, property, context) {
        this.domainName = domainName;
        this.property = property;
        this.context = context;
    },

    onStart: function(dialog) {
        if (this.view == null) {
            this.view = this._createView(this.property, dialog);
        }

        if (this.view) {
            dialog.register(this.view);
            this.view.show(this);
        }
    },

    onResume: function () {
        if (this.context && this.view) {
            if (this.view.variants) {
                var hasParameter = this.context.hasParameter(this.property.id);
                var value = this.context.getParameter(this.property.id);
                this._loadVariants()
                        .done($.proxy(function (values) { values && this.view.variants(values); }, this))
                        .always($.proxy(function () {
                                    hasParameter && this.view.val(value);
                                }, this));
            } else {
                if (this.context.hasParameter(this.property.id)) {
                    this.view.val(this.context.getParameter(this.property.id));
                }
            }
        }
    },

    onPause: function () {
        if (this.view && this.view.valid()) {
            this.context.setParameter(this.property.id, this.view.val());
        }
    },

    onStop: function(dialog) {
        if (this.view) {
            dialog.unregister(this.view);
        }
    },

    onChange: function(view) {
        if (this.context) {
            this.context.setParameter(this.property.id, view.val());
        }
    },

    _loadVariants: function() {
        return $.Deferred().resolve();
    },

    _setupView: function () {
        if (this.context && this.context.hasParameter(this.property.id)) {
            this.view.val(this.context.getParameter(this.property.id));
        }
    },

    _addFieldView: function (property, dialog) {
        if (!!property.advanced) {
            dialog.addAdvancedField(property.html, property.group);
        } else {
            dialog.addFormField(property.html, property.group);
        }
    },

    _createView: function (property, dialog) {
        return null;
    }
});

/** @class */
jscape.domain.ActionContextNotesController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.ActionContextNotesController.prototype} */
{
    onResume: function () {
        if (this.context) {
            this.view.val(this.context.notes);
        }
    },

    onPause: function () {
        if (this.context && this.view.valid()) {
            this.context.notes = this.view.val();
        }
    },

    onChange: function(view) {
        if (this.context) {
            this.context.notes = view.val();
        }
    },

    _createView: function (property, dialog) {
        var id = "_" + $.now().toString(36);
        dialog.addAdvancedField("<div>"
                                + "<label for='" + id + "'>Notes</label>"
                                + "<textarea id='" + id + "' rows='4' cols='42'></textarea>"
                                + "</div>");
        return new jscape.domain.StringPropertyView($("#" + id, dialog.container));
    }
});

/** @class */
jscape.domain.HostKeysPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.HostKeysPropertyController.prototype} */
{
    _loadVariants: function () {
        return $.when(jscape.API.getHostPublicKeys(), jscape.API.getHostCertificates())
                .then(function (publicKeys, certificates) {
                          publicKeys = $.map(publicKeys, function (key) { return key.name; });
                          certificates = $.map(certificates, function (certificate) { return certificate.name; });
                          return publicKeys.concat(certificates);
                      });
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.OptionalComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.PgpPublicKeysPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.PgpPublicKeysPropertyController.prototype} */
{
    _loadVariants: function () {
        return $.when(jscape.API.getPgpPublicKeys(), jscape.API.getPgpSecretKeys())
                .then(function (publicKeys, secretKeys) {
                          publicKeys = $.map(publicKeys, function (key) { return "public: " + key.name; });
                          secretKeys = $.map(secretKeys, function (key) { return "secret: " + key.name; });
                          return publicKeys.concat(secretKeys);
                      });
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.OptionalComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.PgpSecretKeysPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.PgpSecretKeysPropertyController.prototype} */
{
    _loadVariants: function () {
        return jscape.API.getPgpSecretKeys()
                .then(function (keys) { return $.map(keys, function (key) { return key.name; }); });
    },

    _createView: function (property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.OptionalComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.TradingPartnersPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.TradingPartnersPropertyController.prototype} */
{
    protocols: null,

    onCreate: function(_, property, context) {
        this._super.apply(this, arguments);
        this.protocols = property.field.supportedProtocols || [];
    },

    _loadVariants: function() {
        return jscape.API.getTradingPartnerNames(this.domainName, this.protocols);
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.ComboboxPropertyView($("#" + property.id, dialog.container()), true, {limitToList: false, validateOnBlur: true});
    }
});

/** @class */
jscape.domain.DirectoryMonitorsPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.DirectoryMonitorsPropertyController.prototype} */
{
    _loadVariants: function() {
        return jscape.API.getDirectoryMonitorNames(this.domainName);
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.ComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.OwnerPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.OwnerPropertyController.prototype} */
{
    _loadVariants: function() {
        return jscape.API.getAccountAdminNames(this.domainName);
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.OptionalComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.UrlBrandingPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.UrlBrandingPropertyController.prototype} */
{
    _loadVairants: function () {
        return jscape.API.getWebThemeNames(this.domainName);
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.OptionalComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.BasePropertyView = Class.extend(
    /** @lends {jscape.domain.BasePropertyView} */
{
    show: function(listener) {
        this.listener = listener;
    },

    collide: function() {
        return false;
    },

    _collide: function(a, b) {
        return !(a.max.x < b.min.x || a.min.x > b.max.x || a.max.y < b.min.y || a.min.y > b.min.y);
    },

    _onChange: function() {
        this.listener && this.listener.onChange(this);
    },

    _aabb: function(el) {
        var offset = el.offset();
        return {
            min: {x: offset.left, y: offset.top},
            max: {x: offset.left + Math.max(el.outerWidth(), el[0].scrollWidth), y: offset.top + Math.max(el.outerHeight(), el[0].scrollHeight)}
        };
    }
});

/** @class */
jscape.domain.StringPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.StringPropertyController.prototype} */
{
    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.StringPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.StringPropertyView = jscape.domain.BasePropertyView.extend(
    /** @lends {jscape.domain.StringPropertyView.prototype} */
{
    label: null,
    input: null,

    /** @constructor */
    initialize: function(input) {
        this.input = $(input);
        this.label = this.input.parent().find("label[for='" + this.input.attr("id") + "']");

        var maxLength = parseInt(this.input.prop("maxlength"));
        var pattern = this.input.prop("pattern");
        this.input.textbox({
            doSize: false,
            multiline: this.input.is("textarea"),
            onChange: $.proxy(this._onChange, this)
        });
        var opts = this.input.textbox("options");
        if (opts.required && !isNaN(maxLength)) {
            if (maxLength > 0) {
                opts.validType = "length[1," + maxLength + "]";
            } else {
                opts.validType = "length[1," + Number.MAX_VALUE + "]";
                opts.invalidMessage = opts.missingMessage;
            }
        }
        if (pattern && pattern.trim().length != 0) {
            opts.validType = "pattern['" + pattern + "', 'g']";
            opts.invalidMessage = opts.missingMessage;
        }
        this.help = $("#" + this.input.attr("aria-describedby"));
        this.help.tooltip({position: "right", showDelay: 0, content: this.help.html(), onShow: function() {
            $(this).tooltip("tip").addClass("tooltip-tip-black");
            $(this).tooltip("reposition");
        }});
        this.help.empty();
    },

    show: function() {
        this._super.apply(this, arguments);
        if (this.input.textbox("options").multiline) {
            this.input.textbox("resize", {width: "60%", height: 120});
        } else {
            this.input.textbox("resize", {width: "60%"});
        }
    },

    collide: function() {
        return this.label.is(":visible") && this._collide(this._aabb(this.label), this._aabb(this.input.textbox("textbox")));
    },

    valid: function() {
        return this.input.textbox("isValid");
    },

    val: function(value) {
        if (!arguments.length) {
            return this.input.is(":not(:disabled)") ? this.input.textbox("getValue") : null;
        }
        this.input.textbox("setValue", value);
        return this;
    }
});

/** @class */
jscape.domain.BooleanPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.BooleanPropertyController.prototype} */
{
    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.BooleanPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.BooleanPropertyView = jscape.domain.BasePropertyView.extend(
    /** @lends {jscape.domain.BooleanPropertyView.prototype} */
{
    input: null,

    /** @constructor */
    initialize: function (input) {
        this.input = $(input).change($.proxy(this._onChange, this));

        this.help = $("#" + this.input.attr("aria-describedby"));
        this.help.tooltip({position: "right", showDelay: 0, content: this.help.html(), onShow: function() {
            $(this).tooltip("tip").addClass("tooltip-tip-black");
            $(this).tooltip("reposition");
        }});
        this.help.empty();
    },

    collide: function() {
        return false;
    },

    valid: function() {
        return true;
    },

    val: function(value) {
        if (!arguments.length) {
            return this.input.is(":checked");
        }
        this.input.prop("checked", !!value).change();
        return this;
    }
});

/** @class */
jscape.domain.NumberPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.NumberPropertyController.prototype} */
{
    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.NumberPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.NumberPropertyView = jscape.domain.BasePropertyView.extend(
    /** @lends {jscape.domain.NumberPropertyView.prototype} */
{
    label: null,
    input: null,

    /** @constructor */
    initialize: function (input) {
        function _expression(value) { return value.length && /%\w+[()%]?/.test(value); }
        function _expressionChar(c) { return /[%\w\s(),.]/.test(c); }

        this.input = $(input);
        this.label = this.input.parent().find("label[for='" + this.input.attr("id") + "']");
        this.input.numberspinner({
            onChange: $.proxy(this._onChange, this),
            filter: function(e) {
                if (_expression($(this).numberspinner("getValue"))
                    && _expressionChar(String.fromCharCode(e.which))) {
                    return true;
                }
                return $.fn.numberbox.defaults.filter.call(this, e);
            },
            formatter: function(value) {
                return _expression(value) ? value : $.fn.numberbox.defaults.formatter.call(this, value);
            },
            parser: function(value) {
                return _expression(value) ? value : $.fn.numberbox.defaults.parser.call(this, value);
            },
            width: 100
        });

        this.help = $("#" + this.input.attr("aria-describedby"));
        this.help.tooltip({position: "right", showDelay: 0, content: this.help.html(), onShow: function() {
            $(this).tooltip("tip").addClass("tooltip-tip-black");
            $(this).tooltip("reposition");
        }});
        this.help.empty();
    },

    collide: function() {
        return this.label.is(":visible") && this._collide(this._aabb(this.label), this._aabb(this.input.numberspinner("textbox")));
    },

    valid: function() {
        return this.input.numberspinner("isValid");
    },

    val: function(value) {
        if (!arguments.length) {
            return this.input.numberspinner("getValue");
        }
        this.input.numberspinner("setValue", value);
        return this;
    }
});

/** @class */
jscape.domain.ComboboxPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.ComboboxPropertyController.prototype} */
{
    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.ComboboxPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.ComboboxPropertyView = jscape.domain.BasePropertyView.extend(
    /** @lends {jscape.domain.ComboboxPropertyView.prototype} */
{
    label: null,
    input: null,

    /** @constructor */
    initialize: function (input, autocomplete, options) {
        this.input = $(input);
        this.label = this.input.parent().find("label[for='" + this.input.attr("id") + "']");
        this.input.combobox($.extend({
            onChange: $.proxy(this._onChange, this),
            onLoadSuccess: function(data) {
                var c = $(this);
                var opts = c.combo("options");
                if (data.length != 0 && !opts.editable) {
                    c.combobox("clear").combobox("select", data[0].value);
                    }
                opts.panelHeight = data.length > 0 && data.length < 15 ? "auto" : $.fn.combo.defaults.panelHeight;
                c.combo("resize");
            }
        }, options || {}));
        var opts = this.input.combobox("options");
        if (autocomplete && options.limitToList !== false) {
            opts.limitToList = true;
            opts.editable = true;
        }

        this.help = $("#" + this.input.attr("aria-describedby"));
        this.help.tooltip({position: "right", showDelay: 0, content: this.help.html(), onShow: function() {
            $(this).tooltip("tip").addClass("tooltip-tip-black");
            $(this).tooltip("reposition");
        }});
        this.help.empty();
    },

    collide: function() {
        return this.label.is(":visible") && this._collide(this._aabb(this.label), this._aabb(this.input.combobox("textbox")));
    },

    valid: function() {
        return this.input.combobox("isValid");
    },

    variants: function(values) {
        this.input.combobox("loadData", values);
    },

    val: function(value) {
        if (!arguments.length) {
            return this.input.combobox("getValue");
        }
        if (this.input.combobox("options").editable) {
            this.input.combobox("clear").combobox("setValue", value);
        } else {
            if (this.contains(value)) {
                this.input.combobox("clear").combobox("select", value);
            }
        }
        return this;
    },

    contains: function (value) {
        var options = this.input.combobox("options");
        var data = this.input.combobox("getData");
        for (var i = 0; i < data.length; i++) {
            if (data[i][options.valueField] === value) {
                return true;
            }
        }
        return false;
    }
});

/** @class */
jscape.domain.OptionalComboboxPropertyView = jscape.domain.BasePropertyView.extend(
    /** @lends {jscape.domain.OptionalComboboxPropertyView.prototype} */
{
    enableInput: null,
    valueInput: null,

    /** @constructor */
    initialize: function (input) {
        this.valueInput = $(input);
        this.enableInput = $("input[name=use" + this.valueInput.attr("name") + "]:checkbox", this.valueInput.parent());
        this.label = $("#" + this.valueInput.attr("aria-labelledby"));

        this.valueInput.combobox({
            onChange: $.proxy(this._onChange, this),
            onLoadSuccess: $.proxy(function(data) {
                this.valueInput.combobox("clear");
                if (data.length) {
                    this.valueInput.combobox("setValue", data[0].value);
                    $.extend(this.valueInput.combobox("options"), {panelHeight: "auto", panelMinHeight: 100, panelMaxHeight: 300});
                    this.valueInput.combobox("resize");
                    this.enableInput.change();
                } else {
                    this.enableInput.prop("disabled", true).prop("checked", false).change();
                }
            }, this)
        });
        this.enableInput.change($.proxy(function() {
            var enabled = this.enableInput.is(":checked");
            this.valueInput.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
            this._onChange();
        }, this));

        this.help = $("#" + this.valueInput.attr("aria-describedby"));
        this.help.tooltip({position: "right", showDelay: 0, content: this.help.html(), onShow: function() {
            $(this).tooltip("tip").addClass("tooltip-tip-black");
            $(this).tooltip("reposition");
        }});
        this.help.empty();
    },

    collide: function() {
        return this.label.is(":visible") && this._collide(this._aabb(this.label), this._aabb(this.valueInput.combobox("textbox")));
    },

    valid: function () {
        return this.valueInput.combobox("isValid");
    },

    variants: function (values) {
        this.valueInput.combobox("loadData", values);
    },

    val: function (value) {
        if (!arguments.length) {
            return this.enableInput.is(":checked:not(:disabled)") ? this.valueInput.combobox("getValue") : null;
        }
        if (value != null) {
            this.valueInput.combobox("setValue", value);
        }
        this.enableInput.prop("checked", value != null).change();
        return this;
    }
});

/** @class */
jscape.domain.PathPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.PathPropertyController.prototype} */
{
    provider: null,

    /** @constructor */
    initialize: function(provider) {
        this.provider = provider || new jscape.domain.PathPropertyController.PathProvider();
    },

    onBrowse: function (view) {
        return this.provider.browse()
                .done(function (value) { view.val(value); });
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.PathPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.PathPropertyController.FileProvider = Class.extend(
    /** @lends {jscape.domain.PathPropertyController.FileProvider.prototype} */
{
    browse: function() {
        return new SelectPathController($.proxy(jscape.API.listFileSystem, jscape.API),
                                        $.proxy(jscape.API.createFileSystemDir, jscape.API))
                .selectFile()
                .then(function(entry) { return entry.path; });
    }
});

/** @class */
jscape.domain.PathPropertyController.DirectoryProvider = Class.extend(
    /** @lends {jscape.domain.PathPropertyController.DirectoryProvider.prototype} */
{
    browse: function() {
        return new SelectPathController($.proxy(jscape.API.listFileSystem, jscape.API),
                                        $.proxy(jscape.API.createFileSystemDir, jscape.API))
                .selectDirectory()
                .then(function(entry) { return entry.path; });
    }
});

/** @class */
jscape.domain.PathPropertyController.PathProvider = Class.extend(
    /** @lends {jscape.domain.PathPropertyController.PathProvider.prototype} */
{
    browse: function(managementService) {
        return new SelectPathController($.proxy(managementService.listFileSystem, managementService),
                                        $.proxy(managementService.createFileSystemDir, managementService))
                .selectPath()
                .then(function(entry) { return entry.path; });
    }
});

/** @class */
jscape.domain.PathPropertyView = jscape.domain.StringPropertyView.extend(
    /** @lends {jscape.domain.PathPropertyView.prototype} */
{
    /** @constructor */
    initialize: function (input) {
        this._super(input);

        this.input.textbox("textbox").validatebox({tipPosition: "bottom"});
        this.browseButton = $(input).parent("div").find("a[role=button][name^=browse]").linkbutton({onClick: $.proxy(this._onBrowse, this)});
    },

    show: function() {
        this._super.apply(this, arguments);
        this.input.textbox("resize", {width: "55%"});
    },

    _onBrowse: function() {
        if (this.listener) {
            var fieldset = this.input.parents("fieldset");
            fieldset.form("disableValidation");
            this.listener.onBrowse(this)
                    .done($.proxy(function() { this.input.textbox("textbox").select().focus(); }, this))
                    .always(function () { fieldset.form("enableValidation").form("validate"); });
        }
    }
});

/** @class */
jscape.domain.DisableUsersPropertyController = jscape.domain.PropertyController.extend(
    /** @lends {jscape.domain.DisableUsersPropertyController.prototype} */
{
    _loadVariants: function () {
        return jscape.API.getAccountNames(this.domainName).then(function(names) { return names.sort(); });
    },

    _createView: function(property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.DisableUsersPropertyView($("#" + property.id, dialog.container()));
    }
});

/** @class */
jscape.domain.DisableUsersPropertyView = jscape.domain.BasePropertyView.extend(
    /** @lends {jscape.domain.DisableUsersPropertyView.prototype} */
{
    label: null,
    input: null,
    disableUser: null,

    /** @constructor */
    initialize: function (input) {
        input = $(input);
        this.label = input.parent().find("label");
        this.input = input.combobox({
            onChange: $.proxy(this._onChange, this),
            onLoadSuccess: $.proxy(function (data) {
                this.input.combobox("clear");
                if (data.length) {
                    this.input.combobox("setValue", data[0].value);
                    this.input.combo("options").panelHeight = "auto";
                    this.input.combo("resize");
                } else {
                    this.concreteUser.prop("disabled", true);
                }
                this.concreteUser.prop("checked", false).change();
            }, this)
        });

        this.disableUser = $("input[name=disableuser]:radio", this.input.parents("fieldset"));
        this.disableUser.change($.proxy(function() {
            var enabled = this.concreteUser.is(":checked");
            this.input.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
            this._onChange();
        }, this));
        this.concreteUser = this.disableUser.filter("[value=concrete]");
        this.currentUser = this.disableUser.filter("[value=current]");

        this.help = $("#" + this.input.attr("aria-describedby"));
        this.help.tooltip({position: "right", showDelay: 0, content: this.help.html(), onShow: function() {
            $(this).tooltip("tip").addClass("tooltip-tip-black");
            $(this).tooltip("reposition");
        }});
        this.help.empty();
    },

    collide: function() {
        return this.label.is(":visible") && this._collide(this._aabb(this.label), this._aabb(this.input.combobox("textbox")));
    },

    valid: function() {
        return this.concreteUser.is(":checked") ? this.input.combobox("isValid") : true;
    },

    variants: function(values) {
        this.input.combobox("loadData", values);
    },

    val: function(value) {
        if (!arguments.length) {
            return this.concreteUser.is(":checked") ? this.input.combobox("getValue") : null;
        }
        if (value != null) {
            this.input.combobox("setValue", value);
            this.concreteUser.prop("checked", this.input.combobox("getValue") == value).change();
        } else {
            this.currentUser.prop("checked", true).change();
        }
        return this;
    }
});

/** @class */
jscape.domain.AmazonSnsTopicPropertyController = jscape.domain.ComboboxPropertyController.extend(
    /** @lends {jscape.domain.AmazonSnsTopicPropertyController.prototype} */
{
    cache: {params: null, variants: []},

    onLoadVariants: function() {
        return this._loadVariants();
    },

    _loadVariants: function () {
        var params = {domain: this.domainName, partner: this.context.getParameter("Partner")};
        if (params.partner && !Object._equals(this.cache.params, params)) {
            return jscape.API.getTradingPartnerAmazonSnsTopics(params.domain, params.partner)
                    .done($.proxy(function (variants) { this.cache = {variants: variants, params: params}; }, this));
        }
        return $.Deferred().resolve(this.cache.variants);
    },

    _createView: function (property, dialog) {
        this._addFieldView(property, dialog);
        return new jscape.domain.AmazonSnsTopicPropertyView($("#" + property.id, dialog.container()), this);
    }
});

/** @class */
jscape.domain.AmazonSnsTopicPropertyView = jscape.domain.ComboboxPropertyView.extend(
    /** @lends {jscape.domain.AmazonSnsTopicPropertyView.prototype} */
{
    label: null,
    input: null,

    /** @constructor */
    initialize: function (input, listener) {
        this._super(input, false, {
            initialized: false,
            limitToList: false,
            editable: true,
            inputEvents: $.extend({}, $.fn.combobox.defaults.inputEvents, {
                focus: function (e) {
                    $(e.data.target).combobox("reload");
                }
            }),
            onBeforeLoad: function() {
                return !!$(this).combobox("options").initialized;
            },
            loader: function(_, success, error) {
                var icon = $(this).combobox("getIcon", 0);
                if (listener) {
                    icon.removeClass("combo-arrow").addClass("icon-loading");
                    listener.onLoadVariants()
                            .done(success)
                            .fail(error)
                            .always(function () {
                                        icon.removeClass("icon-loading").addClass("combo-arrow");
                                        icon = null;
                                    });
                }

            }
        });
        this.input.combobox("options").initialized = true;
    }
});