jscape.settings = jscape.settings || {};

/** @class */
jscape.AuthenticationService = Class.extend(
    /** @lends {jscape.AuthenticationService.prototype} */
{
    /** @constructor */
    initialize: function(type, role, usernameConversion) {
        this.type = type || null;
        this.role = role || null;
        this.usernameConversion = usernameConversion || jscape.UsernameConversion.NONE;
    }
});
jscape.AuthenticationService.fromJSON = function(data) {
    if (data && data.hasOwnProperty("usernameConversion"))  {
        data.usernameConversion = jscape.UsernameConversion.valueOf(data.usernameConversion);
    }
    return data ? $.extend(new jscape.AuthenticationService(), data) : jscape.AuthenticationService.local();
};
jscape.AuthenticationService.TYPE = {
    LOCAL: "LOCAL", DB: "DB", DB_QUERY: "DB_QUERY", LDAP: "LDAP", LDAP_QUERY: "LDAP_QUERY", NTLM: "NTLM", PAM: "PAM", RADIUS: "RADIUS", CUSTOM: "CUSTOM"
};
jscape.AuthenticationService.local = function() {
    return new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.LOCAL);
};
jscape.AuthenticationService.db = function(url, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.DB, role, usernameConversion), {url: url});
};
jscape.AuthenticationService.dbQuery = function(url, username, password, query, hasher, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.DB_QUERY, role, usernameConversion), {url: url, username: username, password: password, sql: query, hasher: hasher});
};
jscape.AuthenticationService.ldap = function(host, port, timeout, userDN, useSsl, anonymousAllowed, failover, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.LDAP, role, usernameConversion), {host: host, port: port, timeout: timeout, userDN: userDN, useSsl: !!useSsl, anonymousAllowed: !!anonymousAllowed, failoverServers: failover ? [failover] : []});
};
jscape.AuthenticationService.ldapQuery = function(host, port, timeout, userDN, searchUserDN, baseDN, password, hasher, filter, useSsl, anonymousAllowed, failover, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.LDAP_QUERY, role, usernameConversion), {host: host, port: port, timeout: timeout, userDN: userDN, searchUserDN: searchUserDN, baseDN: baseDN, password: password, hasher: hasher, filter: filter, useSsl: !!useSsl, anonymousAllowed: !!anonymousAllowed, failoverServers: failover ? [failover] : []});
};
jscape.AuthenticationService.ntlm = function(host, domain, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.NTLM, role, usernameConversion), {host: host, windowsDomain: domain});
};
jscape.AuthenticationService.pam = function(debug, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.PAM, role, usernameConversion), {debugEnabled: !!debug});
};
jscape.AuthenticationService.radius = function(localHost, serverHost, serverPort, timeout, maxRetransmitAttempts, identifier, sharedSecret, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.RADIUS, role, usernameConversion), {localhost: localHost, localport: 0, serverhost: serverHost, serverport: serverPort, timeout: timeout, maxRetransmitAttempts: maxRetransmitAttempts, identifier: identifier, sharedSecret: sharedSecret});
};
jscape.AuthenticationService.custom = function(className, role, usernameConversion) {
    return $.extend(new jscape.AuthenticationService(jscape.AuthenticationService.TYPE.CUSTOM, role, usernameConversion), {className: className || ""});
};
jscape.UsernameConversion = {
    NONE: 'NONE', UPPERCASE: 'UPPERCASE', LOWERCASE: 'LOWERCASE',
    values: function() { return [this.NONE, this.UPPERCASE, this.LOWERCASE]; },
    valueOf: function(value) { return $.inArray(value, this.values()) != -1 ? value : this.NONE; }
};

/** @class */
jscape.settings.AuthenticationServiceController = Class.extend(
    /** @lends {jscape.settings.AuthenticationServiceController.prototype} */
{
    DEFAULT_DESCRIPTOR: jscape.AuthenticationService.local(),

    descriptor: null,
    view: null,

    onCreate: function(managementService) {
        this.managementService = managementService;

        this.controllers = {
            LOCAL: jscape.settings.LocalAuthenticationServiceController,
            DB: jscape.settings.DbAuthenticationServiceController,
            DB_QUERY: jscape.settings.DbQueryAuthenticationServiceController,
            LDAP: jscape.settings.LdapAuthenticationServiceController,
            LDAP_QUERY: jscape.settings.LdapQueryAuthenticationServiceController,
            NTLM: jscape.settings.NtlmAuthenticationServiceController,
            PAM: jscape.settings.PamAuthenticationServiceController,
            RADIUS: jscape.settings.RadiusAuthenticationServiceController,
            CUSTOM: jscape.settings.CustomAuthenticationServiceController
        };
    },

    onStart: function () {
        if (this.view == null) {
            this.view = new jscape.settings.AuthenticationServiceView();
        }
        this.view.show(this);
    },

    onResume: function () {
        $.when(this.managementService.getManagementAuthenticationServiceConfiguration(),
               this.managementService.getManagementRoles())
                .done($.proxy(function (descriptor, roles) { this.descriptor = descriptor; this.roles = roles || []; }, this))
                .fail($.proxy(function () { this.descriptor = this.DEFAULT_DESCRIPTOR; this.roles = []; }, this))
                .always($.proxy(function () { this.view && this._setupView(this.descriptor.type); }, this));
    },

    hasChanged: function () {
        if (!this.descriptor) {
            return false;
        }
        try {
            var descriptor = this._createDescriptor();
            return descriptor != undefined && !Object._equals(this.descriptor, descriptor);
        } catch (e) {
            return false;
        }
    },

    onApply: function () {
        try {
            var descriptor = this._createDescriptor();
            return this.managementService.setManagementAuthenticationServiceConfiguration(descriptor)
                    .done($.proxy(function () { this.descriptor = descriptor; }, this))
                    .done($.proxy(this._fireApplySuccess, this));
        } catch (e) {
            return $.Deferred().reject().promise();
        }
    },

    onDiscard: function () {
        $.each(this.controllers, function (_, controller) {
            if ($.type(controller) === "object") {
                controller.discardChanges();
            }
        });
        this._setupView(this.descriptor.type);
        return $.Deferred().resolve().promise();
    },

    onChangeType: function () {
        var serviceType = (this.view.getType() || "").toUpperCase();
        $.each(this.controllers, $.proxy(function (type, controller) {
            var t = $.type(controller);
            if (serviceType === type) {
                if (t === "function") {
                    this.controllers[type] = new controller();
                    this.controllers[type].start(this.managementService, this.descriptor, this.roles);
                } else {
                    controller.resume();
                }
            } else {
                if (t === "object") {
                    controller.pause();
                }
            }
        }, this));
    },

    onChangeRoles: function(roles) {
        this.roles = roles || [];
        $.each(this.controllers, $.proxy(function (_, controller) {
            if ($.type(controller) === "object") {
                controller.setRoles(this.roles);
            }
        }, this));
    },

    _createDescriptor: function () {
        var serviceType = (this.view.getType() || "").toUpperCase();
        var type = $.type(this.controllers[serviceType]);
        if (type === "object") {
            return this.controllers[serviceType].applyChanges();
        } else if (type === "function") {
            return undefined;
        } else {
            throw "Unknown service type: " + serviceType;
        }
    },

    _setupView: function (type) {
        this.view.setType(type);
    },

    _fireApplySuccess: function () {
        $(document).triggerHandler("broadcast", [window.R.string.APPLICATION_SUCCESS_APPLY]);
    }
});

/** @class */
jscape.settings.AuthenticationServiceView = Class.extend(
    /** @lends {jscape.settings.AuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.fieldset = $("fieldset[name=authservicefields]");

        this.type = $("select[name=type]", this.fieldset).combobox({required: true, editable: false, selectOnNavigation: false, width: "17%", panelHeight: "auto", onChange: $.proxy(this._onChange$Type, this)});

        this.applyButton = $("a[role=button][name=apply]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ApplyButton, this)});
        this.discardButton = $("a[role=button][name=discard]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$DiscardButton, this)});
    },

    show: function(listener) {
        this.listener = listener || jscape.settings.AuthenticationServiceView.LISTENER;
    },

    getType: function() {
        return this.type.combobox("getValue");
    },

    setType: function(value) {
        var selectedType = this.type.combobox("getValue");
        this.type.combobox("clear").combobox("select", value);
        if (selectedType === value) {
            this._onChange$Type();
        }
    },

    _onChange$Type: function() {
        this.listener.onChangeType(this);
    },

    _onClick$ApplyButton: function () {
        this.applyButton.linkbutton("disable");
        this.listener.onApply()
                .always($.proxy(function () { this.applyButton.linkbutton("enable"); }, this));
    },

    _onClick$DiscardButton: function() {
        this.listener.onDiscard();
    }
});
jscape.settings.AuthenticationServiceView.LISTENER = {
    onChangeType: $.noop,
    onApply: $.noop,
    onDiscard: $.noop
};

/** @class */
jscape.settings.BaseAuthenticationServiceController = Class.extend(
    /** @lends {jscape.settings.BaseAuthenticationServiceController.prototype} */
{
    VARIABLES: ["username", "password"],

    view: null,

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

    onTest: function() {
        return this.testController.start(this.managementService, this._createDescriptor());
    },

    onAddVariable: function(input) {
        this.variableController.start(input, this.VARIABLES);
    },

    start: function(managementService, descriptor, roles) {
        this.managementService = managementService;
        this.descriptor = descriptor;
        this.roles = roles || [];

        this._setupView(this.descriptor, this.roles);
        this.view.show(this);
    },

    setRoles: function(roles) {
        this.roles = roles || [];
        this._setupView(null, roles);
    },

    resume: function () {
        this.view.show(this);
    },

    pause: function () {
        this.view.hide();
    },

    applyChanges: function () {
        return this.view.valid() ? this._createDescriptor() : undefined;
    },

    discardChanges: function() {
        this._setupView(this.descriptor, this.roles);
    },

    _createDescriptor: function () {
        return null;
    },

    _setupView: function (descriptor, roles) {
    }
});

/** @class */
jscape.settings.BaseAuthenticationServiceView = Class.extend(
    /** @lends {jscape.settings.BaseAuthenticationServiceView.prototype} */
{
    focusInField: null,

    /** @constructor */
    initialize: function(fieldset) {
        this.fieldset = fieldset.hide();
        this.fieldset.find(":input").focus($.proxy(this._onFocus$In, this));

        this.useRole = $("input[name=userole]:checkbox", this.fieldset);
        this.useRole.change($.proxy(function() {
            var enabled = this.useRole.is(":checked:not(:disabled)");
            this.role.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
        }, this));
        this.role = $("select[name=role]", this.fieldset).combobox({required: true, editable: false, panelHeight: "auto", width: 170});

        this.useUsernameConversion = $("input[name=useusernameconversion]:checkbox", this.fieldset);
        this.useUsernameConversion.change($.proxy(function() {
            var enabled = this.useUsernameConversion.is(":checked");
            this.usernameConversion.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
        }, this));
        this.usernameConversion = $("select[name=usernameconversion]", this.fieldset);
        this.usernameConversion.combobox({
            required: true,
            editable: false,
            width: 100,
            panelHeight: "auto",
            onLoadSuccess: $.proxy(function(data) {
                if (data.length) {
                    this.usernameConversion.combobox("clear").combobox("select", data[0].value);
                    this.useUsernameConversion.change();
                } else {
                    this.useUsernameConversion.prop("disabled", true).prop("checked", false).change();
                }
            }, this)
        });

        this.testButton = $("a[role=button][name=test]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$TestButton, this)});
        this.addVariableButton = $("a[role=button][name=addvar]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$AddVariableButton, this)});
    },

    getRole: function() {
        return this.role.length && this.useRole.is(":checked:not(:disabled)") ? this.role.combobox("getValue") : null;
    },

    setRole: function(value) {
        if (this.role.length) {
            this.role.combobox("select", value);
            this.useRole.prop("checked", value != null).change();
        }
    },

    setRoles: function(values) {
        if (this.role.length) {
            this.role.combobox("loadData", values);
            if (values && values.length != 0) {
                this.useRole.prop("disabled", false).change();
            } else {
                this.role.combobox("clear");
                this.useRole.prop("checked", false).prop("disabled", true).change();
            }
        }
    },

    getUsernameConversion: function() {
        return this.usernameConversion.length && this.useUsernameConversion.is(":checked:not(:disabled)")
               ? jscape.UsernameConversion.valueOf(this.usernameConversion.combobox("getValue"))
               : jscape.UsernameConversion.NONE;
    },

    setUsernameConversion: function(value) {
        if (this.usernameConversion.length) {
            this.useUsernameConversion.prop("checked", jscape.UsernameConversion.NONE != value).change();
            if (jscape.UsernameConversion.NONE != value) {
                this.usernameConversion.combobox("select", value);
            }
        }
    },

    show: function (listener) {
        this.listener = listener || jscape.settings.BaseAuthenticationServiceView.LISTENER;
        this.focusInField = null;
        this.fieldset.show().form("validate");
    },

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

    valid: function () {
        return this.fieldset.form("validate");
    },

    _onClick$TestButton: function () {
        if (this.valid()) {
            this.testButton.linkbutton("disable");
            this.listener.onTest(this).always($.proxy(function () {
                this.testButton.linkbutton("enable");
            }, this));
        }
    },

    _onClick$AddVariableButton: function() {
        if (this.addVariableButton.length && this.focusInField) {
            this.addVariableButton.linkbutton("disable");
            this.listener.onAddVariable(this.focusInField);
        }
    },

    _onFocus$In: function (e) {
        var field = $(e.target);
        this.focusInField = field.is("[type=text]") || field.is("textarea") ? field : null;
        if (this.addVariableButton.length) {
            this.addVariableButton.linkbutton(!!this.focusInField ? "enable" : "disable");
        }
    }
});
jscape.settings.BaseAuthenticationServiceView.LISTENER = {
    onTest: $.noop,
    onAddVariable: $.noop
};

/** @class */
jscape.settings.LocalAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.LocalAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.view = new jscape.settings.LocalAuthenticationServiceView();
    },

    _createDescriptor: function () {
        return jscape.AuthenticationService.local();
    }
});

/** @class */
jscape.settings.LocalAuthenticationServiceView = Class.extend(
    /** @lends {jscape.settings.LocalAuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.fieldset = $("fieldset[name=localauthfields]").css("border", "none").hide();
    },

    show: function (listener) {
        this.listener = listener;
        this.fieldset.show();
        this.valid();
    },

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

    valid: function() {
        return this.fieldset.form("validate");
    }
});

/** @class */
jscape.settings.DbAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.DbAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.DbAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        return jscape.AuthenticationService.db(this.view.getUrl(),
                                               this.view.getRole(),
                                               this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.DB == descriptor.type) {
            this.view.setUrl(descriptor.url);
            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.DbAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.DbAuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=dbauthfields]"));

        this.url = $("input[name=dburl]", this.fieldset).textbox({
            required: true,
            validType: "length[1,2048]",
            missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_URL,
            invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_URL,
            width: 350
        });
    },

    getUrl: function() {
        return this.url.textbox("getValue").trim();
    },

    setUrl: function(value) {
        this.url.textbox("setValue", value);
    }
});

/** @class */
jscape.settings.DbQueryAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.DbQueryAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.DbQueryAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        return jscape.AuthenticationService.dbQuery(this.view.getUrl(),
                                                    this.view.getUsername(),
                                                    this.view.getPassword(),
                                                    this.view.getQuery(),
                                                    this.view.getHashClass(),
                                                    this.view.getRole(),
                                                    this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.DB_QUERY == descriptor.type) {
            this.view.setUrl(descriptor.url);
            this.view.setUsername(descriptor.username);
            this.view.setPassword(descriptor.password);
            this.view.setQuery(descriptor.sql);
            this.view.setHashClass(descriptor.hasher);
            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.DbQueryAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.DbQueryAuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=dbqueryauthfields]"));

        this.url = $("input[name=dburl]", this.fieldset).textbox({required: true, validType: "length[1,2048]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_URL, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_URL, width: 500});
        this.username = $("input[name=dbuser]", this.fieldset).textbox({required: true, validType: "length[1,50]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_USER, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_USER, width: 250});
        this.password = $("input[name=dbpwd]", this.fieldset).textbox({type: "password", width: 250});
        this.query = $("textarea[name=query]", this.fieldset).textbox({required: true, multiline: true, validType: "length[1,2000]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_QUERY, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_DB_QUERY, width: 610, height: 90});
        this.hashClass = $("input[name=hashclass]", this.fieldset).textbox({width: 310});
    },

    getUrl: function() {
        return this.url.textbox("getValue").trim();
    },

    setUrl: function(value) {
        this.url.textbox("setValue", value);
    },

    getUsername: function() {
        return this.username.textbox("getValue");
    },

    setUsername: function(value) {
        this.username.textbox("setValue", value);
    },

    getPassword: function() {
        return this.password.textbox("getValue");
    },

    setPassword: function(value) {
        this.password.textbox("setValue", value);
    },

    getQuery: function() {
        return this.query.textbox("getValue");
    },

    setQuery: function(value) {
        this.query.textbox("setValue", value);
    },

    getHashClass: function() {
        return this.hashClass.textbox("getValue");
    },

    setHashClass: function(value) {
        this.hashClass.textbox("setValue", value);
    }
});

/** @class */
jscape.settings.LdapAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.LdapAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.LdapAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        var failover = this.view.getFailoverHost() != null  ? {host: this.view.getFailoverHost(), port: this.view.getFailoverPort()} : null;
        return jscape.AuthenticationService.ldap(this.view.getHost(),
                                                 this.view.getPort(),
                                                 this.view.getTimeout(),
                                                 this.view.getUserDN(),
                                                 this.view.isUseSsl(),
                                                 this.view.isAnonymousAllowed(),
                                                 failover,
                                                 this.view.getRole(),
                                                 this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.LDAP == descriptor.type) {
            this.view.setHost(descriptor.host);
            this.view.setPort(descriptor.port);
            this.view.setTimeout(descriptor.timeout);
            this.view.setUserDN(descriptor.userDN);
            this.view.setUseSsl(descriptor.useSsl);
            this.view.setAnonymousAllowed(descriptor.anonymousAllowed);

            if (descriptor.failoverServers.length) {
                this.view.setFailoverHost(descriptor.failoverServers[0].host);
                this.view.setFailoverPort(descriptor.failoverServers[0].port);
            }

            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.LdapAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.LdapAuthenticationServiceView.prototype} */
{
    TIMEOUT_FACTOR: 1000,
    DEFAULT_PORT: 389,
    DEFAULT_TIMEOUT: 30,

    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=ldapauthfields]"));

        this.host = $("input[name=host]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_LDAP_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_LDAP_HOST, width: 410});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, value: this.DEFAULT_PORT, width: 100});
        this.timeout = $("input[name=timeout]", this.fieldset).numberspinner({required: true, min: 1, max: 999, value: this.DEFAULT_TIMEOUT, width: 60});
        this.userDN = $("input[name=userdn]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_USER_DN, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_USER_DN, width: 410});
        this.useSsl = $("input[name=usessl]", this.fieldset);
        this.anonymousAllowed = $("input[name=allowanonymous]", this.fieldset);

        this.useFailover = $("input[name=usefailover]", this.fieldset);
        this.useFailover.change($.proxy(function() {
            var enabled = this.useFailover.is(":checked");
            this.failoverHost.textbox(enabled ? "enable" : "disable").textbox(enabled ? "enableValidation" : "disableValidation").textbox("isValid");
            this.failoverPort.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.failoverHost = $("input[name=failoverhost]", this.fieldset).textbox({required: true, disabled: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_FAILOVER_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_FAILOVER_HOST, width: 410});
        this.failoverPort = $("input[name=failoverport]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 65535, value: this.DEFAULT_PORT, width: 100});
    },

    getHost: function() {
        return this.host.textbox("getValue");
    },

    setHost: function(value) {
        this.host.textbox("setValue", value);
    },

    getPort: function() {
        return parseInt(this.port.numberspinner("getValue"));
    },

    setPort: function(value) {
        this.port.numberspinner("setValue", parseInt(value) || this.DEFAULT_PORT);
    },

    getTimeout: function() {
        return parseInt(this.timeout.numberspinner("getValue")) * this.TIMEOUT_FACTOR;
    },

    setTimeout: function(value) {
        this.timeout.numberspinner("setValue", parseInt(value) / this.TIMEOUT_FACTOR);
    },

    getUserDN: function() {
        return this.userDN.textbox("getValue");
    },

    setUserDN: function(value) {
        this.userDN.textbox("setValue", value);
    },

    isUseSsl: function() {
        return this.useSsl.is(":checked");
    },

    setUseSsl: function(value) {
        this.useSsl.prop("checked", !!value);
    },

    isAnonymousAllowed: function() {
        return this.anonymousAllowed.is(":checked");
    },

    setAnonymousAllowed: function(value) {
        this.anonymousAllowed.prop("checked", !!value);
    },

    getFailoverHost: function() {
        return this.useFailover.is(":checked") ? this.failoverHost.textbox("getValue") : null;
    },

    setFailoverHost: function(value) {
        this.failoverHost.textbox("setValue", value);
        this.useFailover.prop("checked", !!value).change();
    },

    getFailoverPort: function() {
        return parseInt(this.failoverPort.numberspinner("getValue"));
    },

    setFailoverPort: function(value) {
        this.failoverPort.numberspinner("setValue", parseInt(value) || this.DEFAULT_PORT);
    }
});

/** @class */
jscape.settings.LdapQueryAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.LdapQueryAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.LdapQueryAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        var failover = this.view.getFailoverHost() != null  ? {host: this.view.getFailoverHost(), port: this.view.getFailoverPort()} : null;
        return jscape.AuthenticationService.ldapQuery(this.view.getHost(),
                                                      this.view.getPort(),
                                                      this.view.getTimeout(),
                                                      this.view.getUserDN(),
                                                      this.view.getSearchUserDN(),
                                                      this.view.getBaseDN(),
                                                      this.view.getPassword(),
                                                      this.view.getHasher(),
                                                      this.view.getFilter(),
                                                      this.view.isUseSsl(),
                                                      this.view.isAnonymousAllowed(),
                                                      failover,
                                                      this.view.getRole(),
                                                      this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.LDAP_QUERY == descriptor.type) {
            this.view.setHost(descriptor.host);
            this.view.setPort(descriptor.port);
            this.view.setTimeout(descriptor.timeout);
            this.view.setUserDN(descriptor.userDN);
            this.view.setSearchUserDN(descriptor.searchUserDN);
            this.view.setBaseDN(descriptor.baseDN);
            this.view.setPassword(descriptor.password);
            this.view.setHasher(descriptor.hasher);
            this.view.setFilter(descriptor.filter);
            this.view.setUseSsl(descriptor.useSsl);
            this.view.setAnonymousAllowed(descriptor.anonymousAllowed);

            if (descriptor.failoverServers.length) {
                this.view.setFailoverHost(descriptor.failoverServers[0].host);
                this.view.setFailoverPort(descriptor.failoverServers[0].port);
            }

            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.LdapQueryAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.LdapQueryAuthenticationServiceView.prototype} */
{
    TIMEOUT_FACTOR: 1000,
    DEFAULT_TIMEOUT: 30,
    DEFAULT_PORT: 389,

    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=ldapqueryauthfields]"));

        this.host = $("input[name=host]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_LDAP_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_LDAP_HOST, width: 410});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, value: this.DEFAULT_PORT, width: 100});
        this.timeout = $("input[name=timeout]", this.fieldset).numberspinner({required: true, min: 1, max: 999, value: this.DEFAULT_TIMEOUT, width: 60});
        this.userDN = $("input[name=userdn]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_USER_DN, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_USER_DN, width: 410});
        this.searchUserDN = $("input[name=searchuserdn]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_SEARCH_USER_DN, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_SEARCH_USER_DN, width: 410});
        this.password = $("input[name=password]", this.fieldset).textbox({type: "password", width: 410});
        this.baseDN = $("input[name=basedn]", this.fieldset).textbox({width: 410});
        this.filter = $("textarea[name=filter]", this.fieldset).textbox({required: true, multiline: true, validType: "length[1,2000]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_FILTER, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_FILTER, width: 610, height: 90});
        this.hasher = $("input[name=hasher]", this.fieldset).textbox({width: 410});

        this.useSsl = $("input[name=usessl]", this.fieldset);
        this.anonymousAllowed = $("input[name=allowanonymous]", this.fieldset);

        this.useFailover = $("input[name=usefailover]", this.fieldset);
        this.useFailover.change($.proxy(function() {
            var enabled = this.useFailover.is(":checked");
            this.failoverHost.textbox(enabled ? "enable" : "disable").textbox(enabled ? "enableValidation" : "disableValidation").textbox("isValid");
            this.failoverPort.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.failoverHost = $("input[name=failoverhost]", this.fieldset).textbox({required: true, disabled: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_FAILOVER_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_FAILOVER_HOST, width: 410});
        this.failoverPort = $("input[name=failoverport]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 65535, value: this.DEFAULT_PORT, width: 100});
    },

    getHost: function() {
        return this.host.textbox("getValue");
    },

    setHost: function(value) {
        this.host.textbox("setValue", value);
    },

    getPort: function() {
        return parseInt(this.port.numberspinner("getValue"));
    },

    setPort: function(value) {
        this.port.numberspinner("setValue", parseInt(value) || this.DEFAULT_PORT);
    },

    getTimeout: function() {
        return parseInt(this.timeout.numberspinner("getValue")) * this.TIMEOUT_FACTOR;
    },

    setTimeout: function(value) {
        this.timeout.numberspinner("setValue", parseInt(value) / this.TIMEOUT_FACTOR);
    },

    getUserDN: function() {
        return this.userDN.textbox("getValue");
    },

    setUserDN: function(value) {
        this.userDN.textbox("setValue", value);
    },

    getSearchUserDN: function() {
        return this.searchUserDN.textbox("getValue");
    },

    setSearchUserDN: function(value) {
        this.searchUserDN.textbox("setValue", value);
    },

    getBaseDN: function() {
        return this.baseDN.textbox("getValue");
    },

    setBaseDN: function(value) {
        this.baseDN.textbox("setValue", value);
    },

    getPassword: function() {
        return this.password.textbox("getValue");
    },

    setPassword: function(value) {
        this.password.textbox("setValue", value);
    },

    getHasher: function() {
        return this.hasher.textbox("getValue");
    },

    setHasher: function(value) {
        this.hasher.textbox("setValue", value);
    },

    getFilter: function() {
        return this.filter.textbox("getValue");
    },

    setFilter: function(value) {
        this.filter.textbox("setValue", value);
    },

    isUseSsl: function() {
        return this.useSsl.is(":checked");
    },

    setUseSsl: function(value) {
        this.useSsl.prop("checked", !!value);
    },

    isAnonymousAllowed: function() {
        return this.anonymousAllowed.is(":checked");
    },

    setAnonymousAllowed: function(value) {
        this.anonymousAllowed.prop("checked", !!value);
    },

    getFailoverHost: function() {
        return this.useFailover.is(":checked") ? this.failoverHost.textbox("getValue") : null;
    },

    setFailoverHost: function(value) {
        this.failoverHost.textbox("setValue", value);
        this.useFailover.prop("checked", !!value).change();
    },

    getFailoverPort: function() {
        return parseInt(this.failoverPort.numberspinner("getValue"));
    },

    setFailoverPort: function(value) {
        this.failoverPort.numberspinner("setValue", parseInt(value) || this.DEFAULT_PORT);
    }
});

/** @class */
jscape.settings.NtlmAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.NtlmAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.NtlmAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        return jscape.AuthenticationService.ntlm(this.view.getHost(),
                                                 this.view.getDomain(),
                                                 this.view.getRole(),
                                                 this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.NTLM == descriptor.type) {
            this.view.setHost(descriptor.host);
            this.view.setDomain(descriptor.windowsDomain);
            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.NtlmAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.NtlmAuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=ntlmauthfields]"));

        this.host = $("input[name=host]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_NTLM_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_NTLM_HOST, width: 410});
        this.domain = $("input[name=domain]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_NTLM_DOMAIN, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_NTLM_DOMAIN, width: 410});
    },

    getHost: function() {
        return this.host.textbox("getValue");
    },

    setHost: function(value) {
        this.host.textbox("setValue", value);
    },

    getDomain: function() {
        return this.domain.textbox("getValue");
    },

    setDomain: function(value) {
        this.domain.textbox("setValue", value);
    }
});

/** @class */
jscape.settings.PamAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.PamAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.PamAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        return jscape.AuthenticationService.pam(this.view.isDebugEnabled(),
                                                this.view.getRole(),
                                                this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.PAM == descriptor.type) {
            this.view.setDebugEnabled(descriptor.debugEnabled);
            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.PamAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.PamAuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=pamauthfields]"));

        this.debug = $("input[name=debug]:checkbox", this.fieldset);
    },

    isDebugEnabled: function() {
        return this.debug.is(":checked");
    },

    setDebugEnabled: function(value) {
        this.debug.prop("checked", !!value);
    }
});

/** @class */
jscape.settings.RadiusAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.RadiusAuthenticationServiceController.prototype} */
{
    inetAddresses: null,

    /** @constructor */
    initialize: function() {
        this._super();
        this.inetAddresses = [];
        this.view = new jscape.settings.RadiusAuthenticationServiceView();
    },

    /** @override */
    start: function (managementService) {
        ($.proxy(function (_super, _args) {
            managementService.getServerAddresses()
                    .done($.proxy(function (addresses) { this.inetAddresses = addresses; }, this))
                    .fail($.proxy(function () { this.inetAddresses = []; }, this))
                    .always($.proxy(function () { _super.apply(this, _args); }, this));
        }, this))(this._super, arguments);
    },

    /** @override */
    _createDescriptor: function () {
        return jscape.AuthenticationService.radius(this.view.getLocalHost(),
                                                   this.view.getServerHost(),
                                                   this.view.getServerPort(),
                                                   this.view.getTimeout(),
                                                   this.view.getMaxRetransmitAttempts(),
                                                   this.view.getIdentifier(),
                                                   this.view.getSharedSecret(),
                                                   this.view.getRole(),
                                                   this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setAvailableHosts(this.inetAddresses);
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.RADIUS == descriptor.type) {
            this.view.setLocalHost(descriptor.localhost);
            this.view.setServerHost(descriptor.serverhost);
            this.view.setServerPort(descriptor.serverport);
            this.view.setTimeout(descriptor.timeout);
            this.view.setMaxRetransmitAttempts(descriptor.maxRetransmitAttempts);
            this.view.setIdentifier(descriptor.identifier);
            this.view.setSharedSecret(descriptor.sharedSecret);
            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.RadiusAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.RadiusAuthenticationServiceView.prototype} */
{
    DEFAULTS: {serverPort: 1812, timeout: 30, retransmitAttempts: 3},
    TIMEOUT_FACTOR: 1000,

    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=radiusauthfields]"));

        this.localHost = $("select[name=localhost]", this.fieldset).combobox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_HOST, width: 200,  panelHeight: "auto"});
        this.serverHost = $("input[name=serverhost]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_HOST, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_HOST, width: 500});
        this.serverPort = $("input[name=serverport]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, value: this.DEFAULTS.serverPort, width: 100});
        this.timeout = $("input[name=timeout]", this.fieldset).numberspinner({required: true, min: 1, max: 999, value: this.DEFAULTS.timeout, width: 80});

        this.retransmitAttempts = $("input[name=retransmitattempts]", this.fieldset).numberspinner({required: true, min: 1, max: 100, value: this.DEFAULTS.retransmitAttempts, width: 80});
        this.identifier = $("input[name=identifier]", this.fieldset).textbox({required: true, missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_ID, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_ID, width: 500});
        this.sharedSecret = $("input[name=secret]", this.fieldset).textbox({required: true, missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_SECRET, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_RADIUS_SECRET, width: 500});
    },

    getLocalHost: function() {
        return this.localHost.combobox("getValue");
    },

    setLocalHost: function(value) {
        this.localHost.combobox("setValue", value);
    },

    setAvailableHosts: function(values) {
        this.localHost.combobox("loadData", values);
    },

    getServerHost: function() {
        return this.serverHost.textbox("getValue");
    },

    setServerHost: function(value) {
        this.serverHost.textbox("setValue", value);
    },

    getServerPort: function() {
        return parseInt(this.serverPort.numberspinner("getValue"));
    },

    setServerPort: function(value) {
        this.serverPort.numberspinner("setValue", parseInt(value) || this.DEFAULTS.serverPort);
    },

    getTimeout: function() {
        return parseInt(this.timeout.numberspinner("getValue")) * this.TIMEOUT_FACTOR;
    },

    setTimeout: function(value) {
        this.timeout.numberspinner("setValue", parseInt(value) / this.TIMEOUT_FACTOR);
    },

    getMaxRetransmitAttempts: function() {
        return parseInt(this.retransmitAttempts.numberspinner("getValue"));
    },

    setMaxRetransmitAttempts: function(value) {
        this.retransmitAttempts.numberspinner("setValue", parseInt(value) || this.DEFAULTS.retransmitAttempts);
    },

    getIdentifier: function() {
        return this.identifier.textbox("getValue");
    },

    setIdentifier: function(value) {
        this.identifier.textbox("setValue", value);
    },

    getSharedSecret: function() {
        return this.sharedSecret.textbox("getValue");
    },

    setSharedSecret: function(value) {
        this.sharedSecret.textbox("setValue", value);
    }
});

/** @class */
jscape.settings.CustomAuthenticationServiceController = jscape.settings.BaseAuthenticationServiceController.extend(
    /** @lends {jscape.settings.CustomAuthenticationServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super();
        this.view = new jscape.settings.CustomAuthenticationServiceView();
    },

    /** @override */
    _createDescriptor: function () {
        return jscape.AuthenticationService.custom(this.view.getClassName(),
                                                   this.view.getRole(),
                                                   this.view.getUsernameConversion());
    },

    /** @override */
    _setupView: function (descriptor, roles) {
        this.view.setRoles(roles);

        if (descriptor && jscape.AuthenticationService.TYPE.CUSTOM == descriptor.type) {
            this.view.setClassName(descriptor.className);
            this.view.setRole(descriptor.role);
            this.view.setUsernameConversion(descriptor.usernameConversion);
        }
    }
});

/** @class */
jscape.settings.CustomAuthenticationServiceView = jscape.settings.BaseAuthenticationServiceView.extend(
    /** @lends {jscape.settings.CustomAuthenticationServiceView.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("fieldset[name=customauthfields]"));

        this.className = $("input[name=classname]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.AUTHENTICATION_ERROR_BAD_CLASS, invalidMessage: window.R.string.AUTHENTICATION_ERROR_BAD_CLASS, width: 500});
    },

    getClassName: function() {
        return this.className.textbox("getValue");
    },

    setClassName: function(value) {
        this.className.textbox("setValue", value);
    }
});

/** @class */
jscape.settings.TestAuthenticationServiceController = Class.extend(
    /** @lends {jscape.settings.TestAuthenticationServiceController.prototype} */
{
    deferred: null,

    start: function(managementService, descriptor) {
        this.deferred = $.Deferred();
        this.managementService = managementService;
        this.descriptor = descriptor;
        this._createDialog().show(this);
        return this.deferred.promise();
    },

    onSubmit: function(dialog) {
        var data = dialog.isUseToken()
                ? {token: dialog.getToken()}
                : {login: dialog.getUsername(), password: dialog.getPassword(), ip: dialog.getClientIp()};
        dialog.destroy();

        this.managementService.testManagementAuthenticationService(this.descriptor, data)
                .done($.proxy(this._testPassed, this))
                .fail($.proxy(this._testFailed, this));
    },

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

    _createDialog: function() {
        var dialog = new jscape.settings.TestAuthenticationServiceDialog();
        dialog.setUsePassword();
        return dialog;
    },

    _testPassed: function () {
        $.messager.alert(window.R.string.AUTHENTICATION_ERROR_TEST_TITLE,
                         window.R.string.AUTHENTICATION_ERROR_TEST_SUCCESS_MESSAGE,
                         "info");
        this.deferred.resolve();
        this.deferred = null;
    },

    _testFailed: function () {
        this.deferred.reject();
        this.deferred = null;
    }
});

/** @class */
jscape.settings.TestAuthenticationServiceDialog = Class.extend(
    /** @lends {jscape.settings.TestAuthenticationServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-test-auth-service").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=testauthcredentialsfields]", this.dialog);

        this.types = $("input[name=type]:radio", this.fieldset).change($.proxy(this._adjustFieldState, this));
        this.typePassword = this.types.filter("[value=password]");
        this.typeToken = this.types.filter("[value=token]");

        this.username = $("input[name=username]", this.fieldset).textbox({width: "60%"});
        this.password = $("input[name=password]", this.fieldset).textbox({type: "password", width: "60%"});
        this.clientIp = $("input[name=clientip]", this.fieldset).textbox({width: "50%"});
        this.token = $("input[name=token]", this.fieldset).textbox({required: true, width: "60%"});
    },

    getUsername: function() {
        return this.username.textbox("getValue");
    },

    getPassword: function() {
        return this.password.textbox("getValue");
    },

    getClientIp: function() {
        return this.clientIp.textbox("getValue");
    },

    getToken: function() {
        return this.isUseToken() ? this.token.textbox("getValue") : null;
    },

    isUseToken: function() {
        return this.typeToken.is(":checked");
    },

    setUsePassword: function() {
        this.typePassword.prop("checked", true).change();
    },

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

    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;
    },

    _adjustFieldState: function() {
        var useToken = this.isUseToken();
        $.each([this.username, this.password, this.clientIp], function(_, input) { input.textbox(!useToken ? "enable" : "disable"); });
        this.token.textbox(useToken ? "enable" : "disable").textbox(useToken ? "enableValidation" : "disableValidation");

        this.fieldset.form("validate");
    }
});