jscape.domain = jscape.domain || {};

/** @class */
jscape.Service = Class.extend(
    /** @lends {jscape.Service.prototype} */
{
    initialize: function(a, b, c) {
        this.protocol = a || undefined;
        this.host = b || undefined;
        this.port = parseInt(c) || undefined;
    }
});
jscape.Service.fromJSON = function(data) {
    return data ? $.extend(new jscape.Service(data.protocol, data.host, data.port), data) : null;
}
jscape.Service.Protocol = {AFTP: "AFTP", FTP: "FTP", SFTP: "SFTP", OFTP: "OFTP", TFTP: "TFTP", HTTP: "HTTP", WEBDAV: "WEBDAV", AS2: "AS2"};
jscape.Service.FTP_TYPE = {REGULAR: "regular", EXPLICIT_SSL: "explicit SSL", FORCED_EXPLICIT_SSL: "forced explicit SSL", IMPLICIT_SSL: "implicit SSL"};
jscape.Service.ftp = function(host, port, type, key) {
    switch (type) {
        case jscape.Service.FTP_TYPE.EXPLICIT_SSL:
        case jscape.Service.FTP_TYPE.FORCED_EXPLICIT_SSL:
        case jscape.Service.FTP_TYPE.IMPLICIT_SSL:
            return $.extend(new jscape.Service(jscape.Service.Protocol.FTP, host, port), {type: type, keyAlias: key});
        default:
            return $.extend(new jscape.Service(jscape.Service.Protocol.FTP, host, port), {type: jscape.Service.FTP_TYPE.REGULAR});
    }
};
jscape.Service.sftp = function(host, port, authentication, key) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.SFTP, host, port), {authenticationType: authentication, keyAlias: key});
};
jscape.Service.aftp = function(host, port, key, protect) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.AFTP, host, port), {keyAlias: key, protectionRequired: !!protect});
};
jscape.Service.oftp = function(host, port, code, key, useSsl, encryptFile, signFile, bindTransfersUser) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.OFTP, host, port), {identificationCode: code + "", keyAlias: key + "", connectionInitiallySecured: !!useSsl, fileEncryptionRequired: !!encryptFile, fileSignatureRequired: !!signFile, unauthenticatedTransferBinding: bindTransfersUser || null});
};
jscape.Service.tftp = function(host, port, username) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.TFTP, host, port), {username: username});
};
jscape.Service.http = function(plain, secure) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.HTTP), {plain: !!plain, secure: !!secure});
};
jscape.Service.webdav = function(plain, secure) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.WEBDAV), {plain: !!plain, secure: !!secure});
};
jscape.Service.as2 = function(plain, secure) {
    return $.extend(new jscape.Service(jscape.Service.Protocol.AS2), {plain: !!plain, secure: !!secure});
};
/** @class */
jscape.ServiceInfo = Class.extend(
    /** @lends {jscape.ServiceInfo.prototype} */
{
    /** @constructor */
    initialize: function(a, b, c, d, e, f, g, h, i, k) {
        this.id = a || null;
        this.protocol = b || null;
        this.plainAddress = c || null;
        this.secureAddress = d || null;
        this.keyAlias = e || null;
        this.serviceType = f || null;
        this.authenticationType = g || null;
        this.identificationCode = h || null;
        this.username = i || null;
    }
});
jscape.ServiceInfo.fromJSON = function(data) {
    return data ? new jscape.ServiceInfo(data.id, data.protocol, data.plainAddress, data.secureAddress, data.keyAlias, data.serviceType, data.authenticationType, data.identificationCode, data.username) : null;
};

/** @class */
jscape.domain.ServicesModule = jscape.domain.DomainModule.extend(
    /** @lends {jscape.domain.ServicesModule.prototype} */
{
    onCreate: function() {
        this._super.apply(this, arguments);

        this.servicesController = new jscape.domain.ServicesController();
        this.servicesController.onCreate(this.managementService, this.domainName);

        this.ftpController = new jscape.domain.FtpConfigurationController();
        this.ftpController.onCreate(this.managementService, this.domainName);

        this.sftpController = new jscape.domain.SftpConfigurationController();
        this.sftpController.onCreate(this.managementService, this.domainName);

        this.aftpController = new jscape.domain.AftpConfigurationController();
        this.aftpController.onCreate(this.managementService, this.domainName);

        this.oftpController = new jscape.domain.OftpConfigurationController();
        this.oftpController.onCreate(this.managementService, this.domainName);

        this.tftpController = new jscape.domain.TftpConfigurationController();
        this.tftpController.onCreate(this.managementService, this.domainName);

        this.httpController = new jscape.domain.HttpConfigurationController();
        this.httpController.onCreate(this.managementService, this.domainName);

        this.webDavController = new jscape.domain.WebDavConfigurationController();
        this.webDavController.onCreate(this.managementService, this.domainName);
    },

    onStart: function () {
        this.servicesController.onStart();
        this.ftpController.onStart();
        this.sftpController.onStart();
        this.aftpController.onStart();
        this.oftpController.onStart();
        this.tftpController.onStart();
        this.httpController.onStart();
        this.webDavController.onStart();
    },

    onPause: function() {
        this._confirmAndApply($.grep([
                    this.servicesController,
                    this.ftpController,
                    this.sftpController,
                    this.aftpController,
                    this.oftpController,
                    this.tftpController,
                    this.httpController,
                    this.webDavController
                ],
                function (controller) {
                    return controller.hasChanged();
                }));
    },

    onResume: function() {
        this.servicesController.onResume();
        this.ftpController.onResume();
        this.sftpController.onResume();
        this.aftpController.onResume();
        this.oftpController.onResume();
        this.tftpController.onResume();
        this.httpController.onResume();
        this.webDavController.onResume();
    }
});

/** @class */
jscape.domain.ServicesController = jscape.ui.DatagridController.extend(
    /** @lends {jscape.domain.ServicesController.prototype} */
{
    view: null,

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

        this.addController = new jscape.domain.AddServiceController();
        this.editController = new jscape.domain.EditServiceController();
        this.deleteController = new jscape.domain.DeleteServiceController();
    },

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

    onResume: function() {
        this.view.refresh();
    },

    onRefresh: function() {
        return this.managementService.getServiceInfos(this.domainName);
    },

    hasChanged: function() {
        return false;
    },

    onAddService: function () {
        return this.addController.start(this.managementService, this.domainName)
                .done($.proxy(this._serviceAdded, this));
    },

    onEditService: function (service) {
        return this.editController.start(this.managementService, this.domainName, service.protocol, service.id)
                .done($.proxy(this._serviceEdited, this));
    },

    onDeleteService: function (services) {
        return this.deleteController.start(this.managementService, this.domainName, services)
                .done($.proxy(this._serviceDeleted, this, services));
    },

    _serviceAdded: function(service) {
        this._recordAdded(service);
    },

    _serviceEdited: function(service) {
        this._recordEdited(service);
    },

    _serviceDeleted: function (services) {
        this._recordDeleted(services);
    }
});

/** @class */
jscape.domain.ServicesView = jscape.ui.DatagridView.extend(
    /** @lends {jscape.domain.ServicesView.prototype} */
{
    selection: null,

    /** @constructor */
    initialize: function() {
        var initializing = true;

        this.fieldset = $("fieldset[name=servicesfields]");

        this.data = $("table[role=grid][aria-label=services]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            remoteSort: false,
            ctrlSelect: true,
            sortName: "protocol",
            columns: [[
                {field: "protocol", title: $("thead th:nth-child(1)", this.data).text(), sortable: true, width: 60, formatter: $.proxy(function(_, row) { return this._formatProtocol(row); }, this)},
                {field: "host", title: $("thead th:nth-child(2)", this.data).text(), sortable: false, width: 120, formatter: $.proxy(function(_, row) { return this._formatHost(row); }, this)},
                {field: "port", title: $("thead th:nth-child(3)", this.data).text(), sortable: false, width: 100, align: "right", formatter: $.proxy(function(_, row) { return this._formatPort(row); }, this)},
                {field: "keyAlias", title: $("thead th:nth-child(4)", this.data).text(), sortable: false, width: 120},
                {field: "details", title: $("thead th:nth-child(5)", this.data).text(), sortable: false, width: 120, formatter: $.proxy(function(_, row) { return this._formatDetails(row); }, this)}
            ]],
            onSelect: $.proxy(this._adjustState, this),
            onUnselect: $.proxy(this._adjustState, this),
            onDblClickRow: $.proxy(this._onClick$EditButton, this),
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function() { return !initializing; },
            onLoadSuccess: $.proxy(this._adjustState, 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({onClick: $.proxy(this._onClick$EditButton, this)});
        this.deleteButton = $("a[role=button][name=delete]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$DeleteButton, this)});

        initializing = false;
    },

    show: function(listener) {
        this.listener = listener || jscape.domain.ServicesView.LISTENER;
        this._adjustState();
    },

    _formatProtocol: function(service) {
        return window.R.string[("APPLICATION_PROTOCOL_" + service.protocol).toUpperCase()] + (service.type ? " " + service.type : "");
    },

    _formatHost: function (service) {
        switch (service.protocol) {
            case jscape.Service.Protocol.HTTP:
            case jscape.Service.Protocol.WEBDAV:
            case jscape.Service.Protocol.AS2:
                var disabledString = window.R.string.SERVICES_TEMPLATE_DISABLED;
                return window.R.string.SERVICES_TEMPLATE_WEB.supplant({
                    0: service.plainAddress ? this._hostOf(service.plainAddress) : disabledString,
                    1: service.secureAddress ? this._hostOf(service.secureAddress) : disabledString
                });
            default:
                return this._hostOf(service.plainAddress) || this._hostOf(service.secureAddress);
        }
    },

    _formatPort: function(service) {
        switch (service.protocol) {
            case jscape.Service.Protocol.HTTP:
            case jscape.Service.Protocol.WEBDAV:
            case jscape.Service.Protocol.AS2:
                var disabledString = window.R.string.SERVICES_TEMPLATE_DISABLED;
                return window.R.string.SERVICES_TEMPLATE_WEB.supplant({
                    0: service.plainAddress ? this._portOf(service.plainAddress) : disabledString,
                    1: service.secureAddress ? this._portOf(service.secureAddress) : disabledString
                });
            default:
                return this._portOf(service.plainAddress) || this._hostOf(service.secureAddress);
        }
    },

    _formatDetails: function(service) {
        switch (service.protocol) {
            case jscape.Service.Protocol.FTP:
                return service.serviceType || "";
            case jscape.Service.Protocol.SFTP:
                return window.R.string.SERVICES_TEMPLATE_SFTP_DETAILS.supplant({0: service.authenticationType});
            case jscape.Service.Protocol.OFTP:
                return window.R.string.SERVICES_TEMPLATE_OFTP_DETAILS.supplant({0: service.identificationCode});
            case jscape.Service.Protocol.TFTP:
                return window.R.string.SERVICES_TEMPLATE_TFTP_DETAILS.supplant({0: service.username});
            default:
                return "";
        }
    },

    _hostOf: function(address) {
        return address ? ("" + address.host).escapeXml() : "";
    },

    _portOf: function(address) {
        return address ? ("" + address.port).escapeXml() : "";
    },

    _onLoad$Data: function(params, success, error) {
        this.listener.onRefresh(params).done(success).fail(error);
    },

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

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

    _onClick$DeleteButton: function() {
        this.deleteButton.linkbutton("disable");
        this.listener.onDeleteService(this.selection)
                .always($.proxy(function() { this.deleteButton.linkbutton("enable"); }, this));
    },

    _adjustState: function() {
        this.selection = this.data.datagrid("getSelections");
        this.editButton.linkbutton(this.selection.length == 1 ? "enable" : "disable");
        this.deleteButton.linkbutton(this.selection.length != 0 ? "enable" : "disable");
    }
});
jscape.domain.ServicesView.LISTENER = {
    onRefresh: $.noop,
    onAddService: $.noop,
    onDeleteService: $.noop
};

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

    /** @constructor */
    initialize: function() {
        this.controllerMap = {
            AFTP: jscape.domain.AftpServiceController,
            AS2: jscape.domain.As2ServiceController,
            FTP: jscape.domain.FtpServiceController,
            HTTP: jscape.domain.HttpServiceController,
            OFTP: jscape.domain.OftpServiceController,
            SFTP: jscape.domain.SftpServiceController,
            TFTP: jscape.domain.TftpServiceController,
            WEBDAV: jscape.domain.WebDavServiceController
        };
    },

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

    onSubmit: function(dialog) {
        var protocol = dialog.getProtocol();
        dialog.destroy();

        var theClass = this.controllerMap[protocol.toUpperCase()];
        var controller = new theClass();
        controller.start(this.managementService, this.domainName)
                .done($.proxy(function (descriptor) {
                          this.managementService.addService(this.domainName, descriptor)
                                  .done($.proxy(function () { this.deferred.resolve(descriptor); this.deferred = null; }, this))
                                  .fail($.proxy(function () { this.deferred.reject(); this.deferred = null; }, this))
                      }, this))
                .fail($.proxy(function () { this.deferred.reject(); this.deferred = null; }, this));
    },

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

    _setupDialog: function() {
        return new jscape.domain.AddServiceProtocolDialog();
    }
});

/** @class */
jscape.domain.AddServiceProtocolDialog = Class.extend(
    /** @lends {jscape.domain.AddServiceProtocolDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-service-add-protocol").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=serviceprotocolfileds]", this.dialog);

        this.protocol = $("select[name=protocol]", this.fieldset).combobox({required: true, editable: false, width: 150, panelHeight: "auto"});
    },

    getProtocol: function() {
        return this.protocol.combobox("getValue");
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.protocol.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;
    }
});

/** @class */
jscape.domain.EditServiceController = Class.extend(
    /** @lends {jscape.domain.EditServiceController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.controllerMap = {
            AFTP: jscape.domain.AftpServiceController,
            AS2: jscape.domain.As2ServiceController,
            FTP: jscape.domain.FtpServiceController,
            HTTP: jscape.domain.HttpServiceController,
            OFTP: jscape.domain.OftpServiceController,
            SFTP: jscape.domain.SftpServiceController,
            TFTP: jscape.domain.TftpServiceController,
            WEBDAV: jscape.domain.WebDavServiceController
        };
    },

    start: function(managementService, domainName, protocol, id) {
        return managementService.getServiceDescriptor(domainName, protocol, id)
                .then($.proxy(function (descriptor) {
                          return this._controllerFor(protocol)
                                  .start(managementService, domainName, descriptor);
                      }, this))
                .then(function (descriptor) {
                          return managementService.updateService(domainName, protocol, id, descriptor);
                      });
    },

    _controllerFor: function (protocol) {
        protocol = protocol.toUpperCase();
        if (this.controllerMap.hasOwnProperty(protocol)) {
            return new this.controllerMap[protocol]();
        }
        throw "Unknown protocol: " + protocol;
    }
});

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

    start: function(managementService, domainName, services) {
        this.managementService = managementService;
        this.domainName = domainName;
        this.deferred = $.Deferred();
        this._confirmDelete(services)
                .done($.proxy(this._deleteConfirmed, this, services))
                .fail(this.deferred.reject, this.deferred);
        return this.deferred.promise();
    },

    _deleteConfirmed: function (services) {
        $.when.apply(jQuery, $.map(services, $.proxy(function(service) { return this.managementService.deleteService(this.domainName, service.protocol, service.id); }, this)))
                .done($.proxy(function() { this.deferred.resolve(services); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
    },

    _confirmDelete: function (services) {
        var deferred = $.Deferred();
        var win = $.messager.confirm(window.R.string.SERVICES_CONFIRM_DELETE_TITLE,
                           window.R.string.SERVICES_CONFIRM_DELETE_MESSAGE,
                           function (confirmed) {
                               if (confirmed) {
                                   deferred.resolve(confirmed);
                               } else {
                                   deferred.reject();
                               }
                           });
        win.window("body").find(".messager-icon").removeClass("messager-question").addClass("messager-warning");
        return deferred.promise();
    }
});

/** @class */
jscape.domain.FtpServiceController = Class.extend(
    /** @lends {jscape.domain.FtpServiceController.prototype} */
{
    DEFAULTS: {
        "regular": {port: 21, keyUsed: false},
        "explicit SSL": {port: 21, keyUsed: true},
        "forced explicit SSL": {port: 21, keyUsed: true},
        "implicit SSL": {port: 990, keyUsed: true}
    },

    deferred: null,

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

    onChangeType: function(dialog) {
        var type = dialog.getType();
        if (this.DEFAULTS.hasOwnProperty(type)) {
            dialog.setPort(this.DEFAULTS[type].port);
            dialog.setKeyUsed(this.DEFAULTS[type].keyUsed);
        }
    },

    onSubmit: function(dialog) {
        var descriptor = this._createDescriptor(dialog);
        dialog.destroy();
        this.deferred.resolve(descriptor);
        this.deferred = null;
    },

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

    _createDescriptor: function (dialog) {
        return jscape.Service.ftp(dialog.getHost(), dialog.getPort(), dialog.getType(), dialog.getKeyAlias());
    },

    _setupDialog: function (descriptor) {
        var dialog = new jscape.domain.FtpServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({
                0: descriptor.type == jscape.Service.FTP_TYPE.IMPLICIT_SSL
                   ? window.R.string.APPLICATION_PROTOCOL_IMPLICIT_FTPS
                   : descriptor.type == jscape.Service.FTP_TYPE.EXPLICIT_SSL || descriptor.type == jscape.Service.FTP_TYPE.FORCED_EXPLICIT_SSL
                     ? window.R.string.APPLICATION_PROTOCOL_EXPLICIT_FTPS : window.R.string.APPLICATION_PROTOCOL_FTP}));
            dialog.setType(descriptor.type);
            dialog.setHost(descriptor.host);
            dialog.setPort(descriptor.port);
            dialog.setKeyAlias(descriptor.keyAlias);
        } else {
            dialog.setType(jscape.Service.FTP_TYPE.EXPLICIT_SSL);
            this.onChangeType(dialog);
        }
        this.managementService.getServerAddresses().done(function(addresses) { dialog.setHosts(addresses); });
        this.managementService.getServerKeys().done(function(keys) { dialog.setKeys($.map(keys, function (key) { return key.name; })); });
        return dialog;
    }
});

/** @class */
jscape.domain.FtpServiceDialog = Class.extend(
    /** @lends {jscape.domain.FtpServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-services-ftp").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=ftpservicefields]", this.dialog);

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.SERVICES_ERROR_BAD_HOST, invalidMessage: window.R.string.SERVICES_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.type = $("select[name=type]", this.fieldset).combobox({required: true, editable: false, onChange: $.proxy(this._onChange$Type, this), width: 170, panelHeight: "auto"});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170, panelHeight: "auto"});
    },

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

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

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

    setHosts: function(values) {
        this.host.combobox("loadData", values);
    },

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

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

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

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

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeyAlias: function(value) {
        this.keyAlias.combobox("setValue", value);
        this.setKeyUsed(value != null);
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

    setKeyUsed: function(value) {
        this.keyAlias.combobox(!!value ? "enable" : "disable").combobox(!!value ? "enableValidation" : "disableValidation");
    },

    show: function (listener) {
        this.listener = listener || jscape.domain.FtpServiceDialog.LISTENER;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.host.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);
    },

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

    _closed: function () {
        return !!this.dialog.dialog("options").closed;
    }
});
jscape.domain.FtpServiceDialog.LISTENER = {
    onChangeType: $.noop,
    onSubmit: $.noop,
    onCancel: $.noop
};

/** @class */
jscape.domain.SftpServiceController = Class.extend(
    /** @lends {jscape.domain.SftpServiceController.prototype} */
{
    DEFAULT_PORT: 22,

    deferred: null,

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

    onSubmit: function(dialog) {
        var descriptor = this._createDescriptor(dialog);
        dialog.destroy();
        this.deferred.resolve(descriptor);
        this.deferred = null;
    },

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

    _createDescriptor: function (dialog) {
        return jscape.Service.sftp(dialog.getHost(), dialog.getPort(), dialog.getAuthentication(), dialog.getKeyAlias());
    },

    _setupDialog: function(descriptor) {
        var dialog = new jscape.domain.SftpServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({0: window.R.string.APPLICATION_PROTOCOL_SFTP}));
            dialog.setHost(descriptor.host);
            dialog.setPort(descriptor.port);
            dialog.setAuthentication(descriptor.authenticationType);
            dialog.setKeyAlias(descriptor.keyAlias);
        } else {
            dialog.setPort(this.DEFAULT_PORT);
        }
        this.managementService.getServerAddresses().done(function(addresses) { dialog.setHosts(addresses); });
        this.managementService.getServerKeys().done(function(keys) { dialog.setKeys($.map(keys, function (key) { return key.name; })); });
        return dialog;
    }
});

/** @class */
jscape.domain.SftpServiceDialog = Class.extend(
    /** @lends {jscape.domain.SftpServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-services-sftp").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=sftpservicefields]", this.dialog);

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.SERVICES_ERROR_BAD_HOST, invalidMessage: window.R.string.SERVICES_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto"});
        this.auth = $("select[name=auth]", this.fieldset).combobox({required: true, editable: false, width: 170, panelHeight: "auto"});
    },

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

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

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

    setHosts: function(values) {
        this.host.combobox("loadData", values);
    },

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

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

    getAuthentication: function() {
        return this.auth.combobox("getValue");
    },

    setAuthentication: function(value) {
        this.auth.combobox("select", value);
    },

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeyAlias: function(value) {
        this.keyAlias.combobox("setValue", value);
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.host.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;
    }
});

/** @class */
jscape.domain.AftpServiceController = Class.extend(
    /** @lends {jscape.domain.AftpServiceController.prototype} */
{
    DEFAULT_PORT: 3000,

    deferred: null,

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

    onSubmit: function(dialog) {
        var descriptor = this._createDescriptor(dialog);
        dialog.destroy();
        this.deferred.resolve(descriptor);
        this.deferred = null;
    },

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

    _createDescriptor: function (dialog) {
        return jscape.Service.aftp(dialog.getHost(), dialog.getPort(), dialog.getKeyAlias(), dialog.isProtectionRequired());
    },

    _setupDialog: function(descriptor) {
        var dialog = new jscape.domain.AftpServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({0: window.R.string.APPLICATION_PROTOCOL_AFTP}));
            dialog.setHost(descriptor.host);
            dialog.setPort(descriptor.port);
            dialog.setKeyAlias(descriptor.keyAlias);
            dialog.setProtectionRequired(descriptor.protectionRequired);
        } else {
            dialog.setPort(this.DEFAULT_PORT);
        }
        this.managementService.getServerAddresses().done(function(addresses) { dialog.setHosts(addresses); });
        this.managementService.getServerKeys().done(function(keys) { dialog.setKeys($.map(keys, function (key) { return key.name; })); });
        return dialog;
    }
});

/** @class */
jscape.domain.AftpServiceDialog = Class.extend(
    /** @lends {jscape.domain.AftpServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-services-aftp").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=aftpservicefields]", this.dialog);

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.SERVICES_ERROR_BAD_HOST, invalidMessage: window.R.string.SERVICES_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto"});
        this.protectionRequired = $("input[name=requiresecure]:checkbox", this.fieldset);
    },

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

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

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

    setHosts: function(values) {
        this.host.combobox("loadData", values);
    },

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

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

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeyAlias: function(value) {
        this.keyAlias.combobox("setValue", value);
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

    isProtectionRequired: function() {
        return this.protectionRequired.is(":checked");
    },

    setProtectionRequired: function(value) {
        this.protectionRequired.prop("checked", !!value);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.host.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;
    }
});

/** @class */
jscape.domain.OftpServiceController = Class.extend(
    /** @lends {jscape.domain.OftpServiceController.prototype} */
{
    DEFAULT_PORT: 3305,
    DEFAULT_SSL_PORT: 6619,

    deferred: null,

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

    onSubmit: function(dialog) {
        var descriptor = this._createDescriptor(dialog);
        dialog.destroy();
        this.deferred.resolve(descriptor);
        this.deferred = null;
    },

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

    _createDescriptor: function (dialog) {
        return jscape.Service.oftp(dialog.getHost(),
                                   dialog.getPort(),
                                   dialog.getIdCode(),
                                   dialog.getKeyAlias(),
                                   dialog.isUseSsl(),
                                   dialog.isFileEncryptionRequired(),
                                   dialog.isFileSignatureRequired(),
                                   dialog.getBindTransfersUser());
    },

    _setupDialog: function(descriptor) {
        var dialog = new jscape.domain.OftpServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({0: window.R.string.APPLICATION_PROTOCOL_OFTP}));
            dialog.setHost(descriptor.host);
            dialog.setPort(descriptor.port);
            dialog.setUseSsl(descriptor.connectionInitiallySecured);
            dialog.setIdCode(descriptor.identificationCode);
            dialog.setKeyAlias(descriptor.keyAlias);
            dialog.setFileEncryptionRequired(descriptor.fileEncryptionRequired);
            dialog.setFileSignatureRequired(descriptor.fileSignatureRequired);
            dialog.setBindTransfersUser(descriptor.unauthenticatedTransferBinding);
        } else {
            dialog.setPort(this.DEFAULT_PORT);
            dialog.setUseSsl(true);
            dialog.setFileEncryptionRequired(true);
            dialog.setFileSignatureRequired(true);
        }
        this.managementService.getServerAddresses().done(function(addresses) { dialog.setHosts(addresses); });
        this.managementService.getServerKeys().done(function(keys) { dialog.setKeys($.map(keys, function (key) { return key.name; })); });
        this.managementService.getAccountNames(this.domainName).done(function (names) { dialog.setAccounts(names.sort()); });
        return dialog;
    }
});

/** @class */
jscape.domain.OftpServiceDialog = Class.extend(
    /** @lends {jscape.domain.OftpServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-services-oftp").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=tftpservicefields]", this.dialog);

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 210,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.SERVICES_ERROR_BAD_HOST, invalidMessage: window.R.string.SERVICES_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.idCode = $("input[name=idcode]", this.fieldset).textbox({required: true, validType: "length[1,500]", missingMessage: window.R.string.SERVICES_ERROR_BAD_ID_CODE, invalidMessage: window.R.string.SERVICES_BAD_ID_CODE, width: 210});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto"});

        this.useSsl = $("input[name=usessl]:checkbox", this.fieldset);
        this.fileEncryption = $("input[name=fileencryption]:checkbox", this.fieldset);
        this.fileSignature = $("input[name=filesignature]:checkbox", this.fieldset);

        this.bindTransfers = $("input[name=bindtransfers]:checkbox", this.fieldset);
        this.bindTransfers.change($.proxy(function() {
            var enabled = this.bindTransfers.is(":checked:not(:disabled)");
            this.transferUser.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
        }, this));
        this.transferUser = $("select[name=transferuser]", this.fieldset).combobox({required: true, editable: false, width: 170, panelHeight: "auto", missingMessage: window.R.string.SERVICES_ERROR_BAD_UNAUTH_TRANSFER_USER, invalidMessage: window.R.string.SERVICES_ERROR_BAD_UNAUTH_TRANSFER_USER});
    },

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

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

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

    setHosts: function(values) {
        this.host.combobox("loadData", values);
    },

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

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

    getIdCode: function() {
        return this.idCode.textbox("getValue");
    },

    setIdCode: function(value) {
        this.idCode.textbox("setValue", value);
    },

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeyAlias: function (value) {
        this.keyAlias.combobox("setValue", value);
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

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

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

    isFileEncryptionRequired: function() {
        return this.fileEncryption.is(":checked");
    },

    setFileEncryptionRequired: function(value) {
        this.fileEncryption.prop("checked", !!value);
    },

    isFileSignatureRequired: function() {
        return this.fileSignature.is(":checked");
    },

    setFileSignatureRequired: function(value) {
        this.fileSignature.prop("checked", !!value);
    },

    getBindTransfersUser: function () {
        return this.bindTransfers.is(":checked:not(:disabled)") ? this.transferUser.combobox("getValue") : null;
    },

    setBindTransfersUser: function(value) {
        this.bindTransfers.prop("checked", value != null).change();
        if (value) {
            this.transferUser.combobox("setValue", value);
        }
    },

    setAccounts: function(values) {
        this.bindTransfers.prop("disabled", !(values && values.length != 0)).change();
        this.transferUser.combobox("loadData", values);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.bindTransfers.change();
        this.fieldset.form("validate");
        this.host.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;
    }
});

/** @class */
jscape.domain.TftpServiceController = Class.extend(
    /** @lends {jscape.domain.TftpServiceController.prototype} */
{
    DEFAULT_PORT: 69,

    deferred: null,

    start: function (managementService, domainName, descriptor) {
        this.managementService = managementService;
        this.deferred = $.Deferred();
        this.managementService.getAccountNames(domainName)
                .then($.proxy(function (names) {
                          if (names.length == 0) {
                              this._noAccountsErrorMessage();
                              return $.Deferred().reject().promise();
                          }
                          return names;
                      }, this),
                      $.proxy(this._noAccountsErrorMessage, this))
                .done($.proxy(function (accountNames) {
                          this._setupDialog(accountNames, descriptor).show(this);
                      }, this))
                .fail($.proxy(function () {
                          this.deferred.reject();
                          this.deferred = null;
                      }, this));
        return this.deferred.promise();
    },

    onSubmit: function(dialog) {
        var descriptor = this._createDescriptor(dialog);
        dialog.destroy();
        this.deferred.resolve(descriptor);
        this.deferred = null;
    },

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

    _createDescriptor: function (dialog) {
        return jscape.Service.tftp(dialog.getHost(), dialog.getPort(), dialog.getAccount());
    },

    _setupDialog: function(accountNames, descriptor) {
        var dialog = new jscape.domain.TftpServiceDialog();
        dialog.setAccounts(accountNames.sort());
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({0: window.R.string.APPLICATION_PROTOCOL_TFTP}));
            dialog.setHost(descriptor.host);
            dialog.setPort(descriptor.port);
            dialog.setAccount(descriptor.username);
        } else {
            dialog.setPort(this.DEFAULT_PORT);
        }
        this.managementService.getServerAddresses().done(function(addresses) { dialog.setHosts(addresses || []); });
        return dialog;
    },

    _noAccountsErrorMessage: function() {
        $.messager.alert(window.R.string.APPLICATION_ERROR_TITLE, window.R.string.SERVICES_ERROR_NO_ACCOUNTS, "error");
    }
});

/** @class */
jscape.domain.TftpServiceDialog = Class.extend(
    /** @lends {jscape.domain.TftpServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-services-tftp").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=tftpservicefields]", this.dialog);

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.SERVICES_ERROR_BAD_HOST, invalidMessage: window.R.string.SERVICES_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.account = $("select[name=username]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto", missingMessage: window.R.string.SERVICES_ERROR_BAD_ACCOUNT, invalidMessage: window.R.string.SERVICES_ERROR_BAD_ACCOUNT});
    },

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

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

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

    setHosts: function(values) {
        this.host.combobox("loadData", values);
    },

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

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

    getAccount: function() {
        return this.account.combobox("getValue");
    },

    setAccount: function(value) {
        this.account.combobox("setValue", value);
    },

    setAccounts: function(values) {
        this.account.combobox("loadData", values);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.host.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;
    }
});

/** @class */
jscape.domain.BaseWebServiceController = Class.extend(
    /** @lends {jscape.domain.BaseWebServiceController.prototype} */
{
    start: function(managementService, domainName, descriptor) {
        this.deferred = $.Deferred();
        this._setupDialog(descriptor).show(this);
        return this.deferred.promise();
    },

    onSubmit: function(dialog) {
        var descriptor = this._createDescriptor(dialog);
        dialog.destroy();
        this.deferred.resolve(descriptor);
        this.deferred = null;
    },

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

    _createDescriptor: function (dialog) {
        throw "Abstract method";
    },

    _setupDialog: function() {
        throw "Abstract method";
    }
});

/** @class */
jscape.domain.HttpServiceController = jscape.domain.BaseWebServiceController.extend(
    /** @lends {jscape.domain.HttpServiceController.prototype} */
{
    /** @override */
    _createDescriptor: function (dialog) {
        return jscape.Service.http(dialog.isPlain(), dialog.isSecure());
    },

    /** @override */
    _setupDialog: function(descriptor) {
        var dialog = new jscape.domain.HttpServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({
                0: !!descriptor.secure ? window.R.string.APPLICATION_PROTOCOL_HTTPS : window.R.string.APPLICATION_PROTOCOL_HTTP
            }));
            dialog.setPlain(descriptor.plain);
            dialog.setSecure(descriptor.secure);
        } else {
            dialog.setPlain(true);
            dialog.setSecure(true);
        }
        return dialog;
    }
});

/** @class */
jscape.domain.WebDavServiceController = jscape.domain.BaseWebServiceController.extend(
    /** @lends {jscape.domain.WebDavServiceController.prototype} */
{
    /** @override */
    _createDescriptor: function (dialog) {
        return jscape.Service.webdav(dialog.isPlain(), dialog.isSecure());
    },

    /** @override */
    _setupDialog: function(descriptor) {
        var dialog = new jscape.domain.WebDavServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({
                0: !!descriptor.secure ? window.R.string.APPLICATION_PROTOCOL_WEBDAV_SSL : window.R.string.APPLICATION_PROTOCOL_WEBDAV
            }));
            dialog.setPlain(descriptor.plain);
            dialog.setSecure(descriptor.secure);
        } else {
            dialog.setPlain(true);
            dialog.setSecure(true);
        }
        return dialog;
    }
});

/** @class */
jscape.domain.As2ServiceController = jscape.domain.BaseWebServiceController.extend(
    /** @lends {jscape.domain.As2ServiceController.prototype} */
{
    /** @override */
    _createDescriptor: function (dialog) {
        return jscape.Service.as2(dialog.isPlain(), dialog.isSecure());
    },

    /** @override */
    _setupDialog: function(descriptor) {
        var dialog = new jscape.domain.As2ServiceDialog();
        if (descriptor) {
            dialog.setTitle(window.R.string.SERVICES_EDIT_TITLE.supplant({0: window.R.string.APPLICATION_PROTOCOL_AS2}));
            dialog.setPlain(descriptor.plain);
            dialog.setSecure(descriptor.secure);
        } else {
            dialog.setPlain(true);
            dialog.setSecure(true);
        }
        return dialog;
    }
});

/** @class */
jscape.domain.BaseWebServiceDialog = Class.extend(
    /** @lends {jscape.domain.BaseWebServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function(dialog) {
        this.dialog = dialog.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", this.dialog).first();

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

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

    isPlain: function() {
        return this.plain.is(":checked");
    },

    setPlain: function(value) {
        this.plain.prop("checked", !!value);
    },

    isSecure: function() {
        return this.secure.is(":checked");
    },

    setSecure: function(value) {
        this.secure.prop("checked", !!value);
    },

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

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

/** @class */
jscape.domain.HttpServiceDialog = jscape.domain.BaseWebServiceDialog.extend(
    /** @lends {jscape.domain.HttpServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-services-http"));
    }
});

jscape.domain.WebDavServiceDialog = jscape.domain.BaseWebServiceDialog.extend(
    /** @lends {jscape.domain.WebDavServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-services-webdav"));
    }
});

jscape.domain.As2ServiceDialog = jscape.domain.BaseWebServiceDialog.extend(
    /** @lends {jscape.domain.As2ServiceDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-services-as2"));
    }
});