jscape.keystore = jscape.keystore || {};

/** @class */
jscape.GenerateServerKeyData = Class.extend(
    /** @lends {jscape.GenerateServerKeyData.prototype} */
{
    /** @constructor */
    initialize: function (type, length, periodMillis, commonName, organizationUnit, organization, locality, state, country, keyUsage, keyUsageExtended, crlUrl, signingKey) {
        this.keyType = type || "RSA";
        this.keyLength = parseInt(length) || 1024;
        this.periodMillis = parseInt(periodMillis) || 365 * 24 * 60 * 60 * 1000;
        this.commonName = commonName || "";
        this.organizationUnit = organizationUnit || "";
        this.organization = organization || "";
        this.locality = locality || "";
        this.state = state || "";
        this.country = country || "";
        this.keyUsage = keyUsage || [];
        this.keyUsageExtended = keyUsageExtended || [];
        this.crlUrl = crlUrl || "";
        this.signingKey = signingKey;
    }
});

/** @class */
jscape.keystore.ServerKeysModule = jscape.keystore.KeystoreModule.extend(
    /** @lends {jscape.keystore.ServerKeysModule.prototype} */
{
    /** @constructor */
    initialize: function () {
        this.controller = new jscape.keystore.ServerKeysController();
    },

    onStart: function () {
        this._super();

        this.controller.start(this.managementService);
    },

    onResume: function() {
        this.controller.onResume();
    }
});

/** @class */
jscape.keystore.ServerKeysController = Class.extend(
    /** @lends {jscape.keystore.ServerKeysController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.view = new jscape.keystore.ServerKeysView();

        this.importKeyController = new jscape.keystore.ImportServerKeyController();
        this.importCertificateController = new jscape.keystore.ImportServerCertificateController();
        this.exportPublicKeyController = new jscape.keystore.ExportServerPublicKeyController();
        this.exportPrivateKeyController = new jscape.keystore.ExportServerPrivateKeyController();
        this.exportCertificateController = new jscape.keystore.ExportServerCertificateController();
        this.generateKeyController = new jscape.keystore.GenerateServerKeyController();
        this.generateCrlController = new jscape.keystore.GenerateServerKeyCrlСontroller();
        this.verifyCrlController = new jscape.keystore.VerifyServerKeyRevocationСontroller();
        this.viewController = new jscape.keystore.ViewServerKeyController();
        this.generateCsrController = new jscape.keystore.GenerateServerKeyCsrController();
        this.generateCertificateController = new jscape.keystore.GenerateServerKeyCertificateController();
        this.revokeController = new jscape.keystore.RevokeServerKeyController();
        this.deleteController = new jscape.keystore.DeleteServerKeyController();

        this._initValidators();
    },

    start: function(managementService) {
        this.managementService = managementService;
        this.view.show(this);
    },

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

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

    onImport: function() {
        this.importKeyController.start(this.managementService)
                .done($.proxy(this._keyImported, this));
    },

    onImportCertificates: function(key) {
        this.importCertificateController.start(this.managementService, key.name);
    },

    onExportPrivateKey: function(key) {
        this.exportPrivateKeyController.start(this.managementService, key.name);
    },

    onExportPublicKey: function(key) {
        this.exportPublicKeyController.start(this.managementService, key.name);
    },

    onExportCertificate: function(certificate) {
        this.exportCertificateController.start(this.managementService, certificate.name);
    },

    onGenerateCertificateRevocationList: function() {
        this.generateCrlController.start(this.managementService);
    },

    onVerifyRevocation: function() {
        this.verifyCrlController.start(this.managementService)
                .done($.proxy(function() { this.view.refresh(); }, this));
    },

    onView: function(key) {
        return this.viewController.start(this.managementService, key.name);
    },

    onGenerate: function() {
        this.generateKeyController.start(this.managementService)
                .done($.proxy(this._keyGenerated, this));
    },

    onGenerateCertificateSigningRequest: function(key) {
        this.generateCsrController.start(this.managementService, key.name);
    },

    onGenerateCertificate: function(key) {
        this.generateCertificateController.start(this.managementService, key)
                .done($.proxy(this._certificateGenerated, this));
    },

    onRevokeCertificate: function(certificate) {
        return this.revokeController.start(this.managementService, certificate)
                .done($.proxy(this._certificateRevoked, this));
    },

    onDelete: function(key) {
        this.deleteController.start(this.managementService, key.name)
                .done($.proxy(this._keyDeleted, this, key));
    },

    _keyImported: function(key) {
        this.view.getKeys().push(key);
        this.view.addItem(key);
        this.view.selectItem(key);
    },

    _keyGenerated: function(key) {
        this.view.getKeys().push(key);
        this.view.addItem(key);
        this.view.selectItem(key);
    },

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

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

    _keyDeleted: function(key) {
        var keys = this.view.getKeys();
        var index = $.inArray(key, keys);
        if (index != -1) {
            keys.splice(index, 1);
            this.view.deleteItem(key);
        }
        if (keys.length) {
            index = Math.max(0, Math.min(index, keys.length - 1));
            this.view.selectItem(keys[index]);
        }
    },

    _initValidators: function() {
        var v = new jscape.Validator();
        v.rule("serverkeys_notexists", $.proxy(this._keyAliasNotExists, this), window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_ALIAS_EXISTS);
    },

    _keyAliasNotExists: function(value, excludes) {
        var aliases = $.map(this.view.getKeys(), function(key) { return excludes && $.inArray(key.name, excludes) != -1 ? null : key.name; });
        return $.inArray(value, aliases) == -1;
    }
});

/** @class */
jscape.keystore.ServerKeysView = Class.extend(
    /** @lends {jscape.keystore.ServerKeysView.prototype} */
{
    DATE_FORMAT: new jscape.DateFormat("{MM}-{dd}-{yy}"),

    selection: null,

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

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

        this.data = $("table[role=grid][aria-label=serverkeys]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            remoteSort: false,
            singleSelect: true,
            idField: "name",
            sortName: "name",
            columns: [[
                    {field: "name", title: $("thead th:nth-child(1)", this.data).text(), sortable: true, width: 120},
                    {field: "keyAlgorithm", title: $("thead th:nth-child(2)", this.data).text(), sortable: true, width: 70},
                    {field: "keySize", title: $("thead th:nth-child(3)", this.data).text(), sortable: true, width: 70},
                    {field: "certificateSerialNumber", title: $("thead th:nth-child(4)", this.data).text(), sortable: true, width: 100},
                    {field: "certificateIssuer", title: $("thead th:nth-child(5)", this.data).text(), sortable: false, width: 120},
                    {field: "certificateSubject", title: $("thead th:nth-child(6)", this.data).text(), sortable: false, width: 120},
                    {field: "certificateBeginDate", title: $("thead th:nth-child(7)", this.data).text(), sortable: true, width: 100, formatter: $.proxy(this._formatDate, this), styler: $.proxy(this._styleDate, this, true)},
                    {field: "certificateEndDate", title: $("thead th:nth-child(8)", this.data).text(), sortable: true, width: 100, formatter: $.proxy(this._formatDate, this), styler: $.proxy(this._styleDate, this, false)},
                    {field: "revoked", title: $("thead th:nth-child(9)", this.data).text(), sortable: true, width: 60, align: "center", formatter: function(value) { return "<input type=\"checkbox\" onclick=\"return false\"" + (value ? " checked=\"checked\" />" : "/>"); }},
                    {field: "domains", title: $("thead th:nth-child(10)", this.data).text(), sortable: true, width: 100, formatter: function(values) { return values ? values.join(", ").escapeXml() : null; }}
            ]],
            onSelect: $.proxy(this._adjustButtonsState, this),
            onUnselect: $.proxy(this._adjustButtonsState, this),
            onDblClickRow: $.proxy(this._onClick$ViewButton, this),
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function() { return !initializing; },
            onLoadSuccess: $.proxy(this._adjustButtonsState, this)
        });

        this.generateButton = $("a[role=button][name=generate]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$GenerateButton, this)});
        this.generateMenu = $("div[role=menu][aria-label=generate-menu]", this.fieldset).menu({onClick: $.proxy(this._onMenu$Generate, this)});
        this.importButton = $("a[role=button][name=import]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ImportButton, this)});
        this.importMenu = $("div[role=menu][aria-label=import-menu]", this.fieldset).menu({onClick: $.proxy(this._onMenu$Import, this)});
        this.exportButton = $("a[role=button][name=export]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ExportButton, this)});
        this.exportMenu = $("div[role=menu][aria-label=export-menu]", this.fieldset).menu({onClick: $.proxy(this._onMenu$Export, this)});
        this.crlButton = $("a[role=button][name=crl]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$CrlButton, this)});
        this.crlMenu = $("div[role=menu][aria-label=crl-menu]", this.fieldset).menu({onClick: $.proxy(this._onMenu$Crl, this)});
        this.viewButton = $("a[role=button][name=view]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ViewButton, this)});
        this.revokeButton = $("a[role=button][name=revoke]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$RevokeButton, 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.keystore.ServerKeysView.LISTENER;
        this._adjustButtonsState();
    },

    refresh: function() {
        this.data.datagrid("reload");
    },


    addItem: function(value) {
        this.data.datagrid("appendRow", value);
    },

    deleteItem: function(value) {
        var index = this.data.datagrid("getRowIndex", value);
        if (index >= 0) {
            this.data.datagrid("deleteRow", index);
        }
        this._adjustButtonsState();
    },

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

    getKeys: function() {
        return this.data.datagrid("getData").keys;
    },

    _formatDate: function(value) {
        return $.isNumeric(value) ? this.DATE_FORMAT.format(new Date(value)) : null;
    },

    _styleDate: function(before, value) {
        if ($.isNumeric(value)) {
            var now = new Date().getTime();
            return before && value > now || !before && value < now ? "color:red" : "color:green";
        }
        return null;
    },

    _onLoad$Data: function(_, success, error) {
        this.data.datagrid("unselectAll");
        this.listener.onRefresh()
                .then(function(keys) { return {total: keys.length, rows: [].concat(keys), keys: keys}; })
                .done(success)
                .fail(error);
    },

    _onClick$GenerateButton: function() {
        this.generateMenu.menu("show", {alignTo: this.generateButton});
        this.generateButton.blur();
    },

    _onMenu$Generate: function(item) {
        var type = $(item.target).attr("aria-label");

        if ("menu-key" == type) {
            this.listener.onGenerate();
        } else if ("menu-crt" == type) {
            this.listener.onGenerateCertificate(this.selection);
        } else if ("menu-csr" == type) {
            this.listener.onGenerateCertificateSigningRequest(this.selection);
        }
    },

    _onClick$ImportButton: function() {
        this.importMenu.menu("show", {alignTo: this.importButton});
        this.importButton.blur();
    },

    _onMenu$Import: function(item) {
        var type = $(item.target).attr("aria-label");

        if ("menu-key" == type) {
            this.listener.onImport();
        } else if ("menu-crt" == type) {
            this.listener.onImportCertificates(this.selection);
        }
    },

    _onClick$ExportButton: function() {
        this.exportMenu.menu("show", {alignTo: this.exportButton});
        this.exportButton.blur();
    },

    _onMenu$Export: function(item) {
        var type = $(item.target).attr("aria-label");

        if ("menu-crt" == type) {
            this.listener.onExportCertificate(this.selection);
        } else if ("menu-pubkey" == type) {
            this.listener.onExportPublicKey(this.selection);
        } else if ("menu-prvkey" == type) {
            this.listener.onExportPrivateKey(this.selection);
        }
    },

    _onClick$ViewButton: function() {
        this.listener.onView(this.selection);
    },

    _onClick$RevokeButton: function() {
        this.listener.onRevokeCertificate(this.selection);
    },

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

    _onClick$CrlButton: function() {
        this.crlMenu.menu("show", {alignTo: this.crlButton});
        this.crlButton.blur();
    },

    _onMenu$Crl: function(item) {
        var type = $(item.target).attr("aria-label");

        if ("menu-crl-generate" == type) {
            this.listener.onGenerateCertificateRevocationList();
        } else if ("menu-crl-verify" == type) {
            this.listener.onVerifyRevocation();
        }
    },

    _adjustButtonsState: function () {
        this.selection = this.data.datagrid("getSelected");
        var enabled = this.selection != null;
        this.generateMenu.menu(enabled ? "enableItem" : "disableItem", this.generateMenu.find("[aria-label=menu-crt]"));
        this.generateMenu.menu(enabled ? "enableItem" : "disableItem", this.generateMenu.find("[aria-label=menu-csr]"));
        this.importMenu.menu(enabled ? "enableItem" : "disableItem", this.importMenu.find("[aria-label=menu-crt]"));
        this.exportButton.linkbutton(enabled ? "enable" : "disable");
        this.viewButton.linkbutton(enabled ? "enable" : "disable");
        this.deleteButton.linkbutton(enabled ? "enable" : "disable");
        this.revokeButton.linkbutton(enabled ? "enable" : "disable");
    }
});
jscape.keystore.ServerKeysView.LISTENER = {
    onRefresh: $.noop,
    onImport: $.noop,
    onImportCertificates: $.noop,
    onExportCertificate: $.noop,
    onExportPublicKey: $.noop,
    onExportPrivateKey: $.noop,
    onVerifyRevocation: $.noop,
    onGenerateCertificateRevocationList: $.noop,
    onGenerate: $.noop,
    onGenerateCertificateSigningRequest: $.noop,
    onGenerateCertificate: $.noop,
    onRevokeCertificate: $.noop,
    onView: $.noop,
    onDelete: $.noop
};

jscape.keystore.ImportServerKeyController = Class.extend(
    /** @lends {jscape.keystore.ImportServerKeyController.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        this.managementService.importServerKey(dialog.getAlias(),
                                               dialog.getFile(),
                                               dialog.getFilePassword(),
                                               dialog.getKeyAlias(),
                                               dialog.getKeyPassword(),
                                               dialog.getCertificateFile() || undefined,
                                               dialog.getCertificateFilePassword(),
                                               dialog.getCerfiticateAlias())
                .done($.proxy(function (key) { this.deferred.resolve(key); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function() {
        return new jscape.keystore.ImportServerKeyDialog();
    }
});

/** @class */
jscape.keystore.ImportServerKeyDialog = Class.extend(
    /** @lends {jscape.keystore.ImportServerKeyDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-import").clone().attr("id", "");
        this.dialog.dialog({
            width: 600, 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=importserverkeyfields]", this.dialog);

        this.alias = $("input[name=alias]", this.fieldset).textbox({required: true, validType: "non_empty", missingMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_ALIAS, invalidMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_ALIAS, width: "60%"});
        this.file = $("input[name=file]", this.fieldset).filebox({required: true, validType: "non_empty", validateOnBlur: true, missingMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_FILE, invalidMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_FILE, width: "60%"});
        this.filePassword = $("input[name=filepwd]", this.fieldset).passwordbox({lastDelay: 0, validateOnBlur: true, width: "50%"});
        this.keyAlias = $("input[name=keyalias]", this.fieldset).textbox({width: "50%"});
        this.keyPassword = $("input[name=keypwd]", this.fieldset).passwordbox({lastDelay: 0, validateOnBlur: true, width: "50%"});

        this.certificateFile = $("input[name=crtfile]", this.fieldset).filebox({width: "60%"});
        this.certificateFilePassword = $("input[name=crtfilepwd]", this.fieldset).passwordbox({lastDelay: 0, validateOnBlur: true, width: "50%"});
        this.certificateAlias = $("input[name=crtalias]", this.fieldset).textbox({width: "50%"});
    },

    getAlias: function() {
        return this.alias.textbox("getValue");
    },

    setAlias: function(value) {
        this.alias.textbox("setValue", value);
        if (value) {
            this.alias.textbox("textbox").validatebox("options").validType = ["non_empty", "serverkeys_notexists['" + value + "']"];
        }
    },

    getFile: function () {
        var files = $("#" + this.file.filebox("options").fileboxId)[0].files;
        return files && files.length ? files[0] : null;
    },

    getFilePassword: function () {
        return this.filePassword.passwordbox("getValue");
    },

    getKeyAlias: function () {
        return this.keyAlias.textbox("getValue");
    },

    getKeyPassword: function () {
        return this.keyPassword.passwordbox("getValue");
    },

    getCertificateFile: function() {
        var files = $("#" + this.certificateFile.filebox("options").fileboxId)[0].files;
        return files && files.length ? files[0] : null;
    },

    getCertificateFilePassword: function() {
        return this.certificateFilePassword.passwordbox("getValue");
    },

    getCerfiticateAlias: function() {
        return this.certificateAlias.textbox("getValue");
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.alias.textbox("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.keystore.ImportServerCertificateController = Class.extend(
    /** @lends {jscape.keystore.ImportServerCertificateController.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        this.managementService.importServerKeyCertificates(this.keyAlias,
                                                           dialog.getFile(),
                                                           dialog.getFilePassword(),
                                                           dialog.getAlias())
                .done($.proxy(function () { this.deferred.resolve(); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function() {
        return new jscape.keystore.ImportServerCertificatesDialog();
    }
});

/** @class */
jscape.keystore.ImportServerCertificatesDialog = Class.extend(
    /** @lends {jscape.keystore.ImportServerCertificatesDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-importcrt").clone().attr("id", "");
        this.dialog.dialog({
            width: 600, 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=importserverkeycrtfields]", this.dialog);

        this.file = $("input[name=file]", this.fieldset).filebox({required: true, validType: "non_empty", missingMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_FILE, invalidMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_FILE, width: "65%"});
        this.filePassword = $("input[name=filepwd]", this.fieldset).passwordbox({lastDelay: 0, validateOnBlur: true, width: "50%"});
        this.alias = $("input[name=alias]", this.fieldset).textbox({width: "50%"});
    },

    getFile: function() {
        var files = $("#" + this.file.filebox("options").fileboxId)[0].files;
        return files && files[0];
    },

    getFilePassword: function() {
        return this.filePassword.passwordbox("getValue");
    },

    getAlias: function() {
        return this.alias.textbox("getValue");
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.file.filebox("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.keystore.ExportServerPublicKeyController = Class.extend(
    /** @lends {jscape.keystore.ExportServerPublicKeyController.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        this.managementService.exportServerPublicKey(this.keyAlias,
                                                     dialog.getFormat(),
                                                     dialog.getFilename())
                .done($.proxy(function () { this.deferred.resolve(); }, this))
                .fail($.proxy(function () { this.deferred.reject(); }, this))
                .always($.proxy(function () { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function () {
        var dialog = new jscape.keystore.ExportPublicKeyDialog();
        dialog.setFilename(this.keyAlias + ".pub");
        return dialog;
    }
});

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

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

    onSubmit: function(dialog) {
        this.managementService.exportServerPrivateKey(this.keyAlias,
                                                      dialog.getFormat(),
                                                      dialog.getPassword(),
                                                      dialog.getFilename())
                .done($.proxy(function () { this.deferred.resolve(); }, this))
                .fail($.proxy(function () { this.deferred.reject(); }, this))
                .always($.proxy(function () { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function () {
        var dialog = new jscape.keystore.ExportPrivateKeyDialog();
        dialog.setFilename(this.keyAlias + ".prv");
        return dialog;
    }
});


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

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

    onSubmit: function(dialog) {
        this.managementService.exportServerCertificate(this.alias,
                                                       dialog.getFormat(),
                                                       dialog.getFilename())
                .done($.proxy(function () { this.deferred.resolve(); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function() {
        var dialog = new jscape.keystore.ExportCertificateDialog();
        dialog.setFilename(this.alias + ".crt");
        return dialog;
    }
});

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

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

    onSubmit: function(dialog) {
        var alias = dialog.getAlias();
        var data = this._createData(dialog);
        this.managementService.generateServerKey(dialog.getAlias(), data)
                .done($.proxy(function(key) { this.deferred.resolve(key); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _createData: function (dialog) {
        return new jscape.GenerateServerKeyData(dialog.getAlgorithm(),
                                                dialog.getKeyLength(),
                                                dialog.getPeriod(),
                                                dialog.getCommonName(),
                                                dialog.getOrganizationUnit(),
                                                dialog.getOrganization(),
                                                dialog.getLocality(),
                                                dialog.getState(),
                                                dialog.getCountry(),
                                                dialog.getKeyUsage(),
                                                dialog.getKeyUsageExtended(),
                                                dialog.getCrlUrl(),
                                                dialog.getSigningKey());
    },

    _setupDialog: function () {
        var dialog = new jscape.keystore.GenerateServerKeyDialog();
        dialog.setAlgorithms(jscape.KeyPairAlgorithm.values());
        this.managementService.getServerKeys()
                .done($.proxy(function(keys) { dialog.setSigningKeys($.map(keys, function(key) { return key.name; })); }, this));
        return dialog;
    }
});

/** @class */
jscape.keystore.GenerateServerKeyDialog = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyDialog.prototype} */
{
    PERIOD_FACTOR: 24 * 60 * 60 * 1000,

    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-generate").clone().attr("id", "");
        this.dialog.dialog({
            width: 630, 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.tabs = $("div[role=tablist]", this.dialog).tabs({tabPosition: "top", plain: true});
        this.fieldset = $("fieldset[name=generateserverkeyfields]", this.dialog);

        this.alias = $("input[name=alias]", this.fieldset).textbox({required: true, validType: ["non_empty", "serverkeys_notexists"], missingMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_ALIAS, invalidMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_ALIAS, width: "60%"});
        this.keyAlgorithm = $("select[name=algorithm]", this.fieldset).combobox({editable: false, width: 80, panelHeight: "auto", onChange: $.proxy(this._adjustKeyLength, this)});
        this.keyLength = $("select[name=length]", this.fieldset).combobox({editable: false, width: 80, panelHeight: "auto"});
        this.period = $("input[name=period]", this.fieldset).numberspinner({min: 1, max: 10000, value: 365, increment: 10, width: 80});
        this.commonName = $("input[name=commonname]", this.fieldset).textbox({required: true, validType: "non_empty", missingMessage: window.R.string.KEY_MANAGER_ERROR_BAD_COMMON_NAME, invalidMessage: window.R.string.KEY_MANAGER_ERROR_BAD_COMMON_NAME, width: "50%"});
        this.organizationUnit = $("input[name=organizationunit]", this.fieldset).textbox({width: "50%"});
        this.organization = $("input[name=organization]", this.fieldset).textbox({width: "50%"});
        this.locality = $("input[name=locality]", this.fieldset).textbox({width: "50%"});
        this.state = $("input[name=state]", this.fieldset).textbox({width: "50%"});
        this.country = $("input[name=country]", this.fieldset).textbox({width: "50%"});

        this.keyUsage = $("input[name=keyusage]:checkbox", this.fieldset);
        this.keyUsageExtended = $("input[name=keyusageextended]:checkbox", this.fieldset);
        this.crlUrl = $("input[name=crl]", this.fieldset).textbox({validType: "url", width: "60%"});
        this.signWith = $("input[name=signwith]:checkbox")
                .change($.proxy(function () {
                            var enabled = this.signWith.is(":checked:not(:disabled)");
                            this.signingKey.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
                        }, this));
        this.signingKey = $("select[name=serverkeys]", this.fieldset)
                .combobox({required: true, editable: false, disabled: true, width: 200, panelHeight: "auto",
                              onLoadSuccess: $.proxy(function (data) {
                                  if (data.length == 0) {
                                      this.signWith.prop("disabled", true).change();
                                  } else {
                                      this.signingKey.combobox("select", data[0].value);
                                  }
                              }, this)
                          });
    },

    getAlias: function() {
        return this.alias.textbox("getValue");
    },

    getAlgorithm: function() {
        return this.keyAlgorithm.combobox("getValue");
    },

    setAlgorithms: function(values) {
        var data = $.map(values || [], function(item) { return {text: item.name, value: item.name}; });
        this.keyAlgorithm.combobox("loadData", data);
    },

    getKeyLength: function() {
        return this.keyLength.combobox("getValue");
    },

    setKeyLengths: function (values) {
        this.keyLength.combobox("loadData", values);
    },

    getPeriod: function() {
        return parseInt(this.period.numberspinner("getValue")) * this.PERIOD_FACTOR;
    },

    getCommonName: function() {
        return this.commonName.textbox("getValue");
    },

    getOrganizationUnit: function() {
        return this.organizationUnit.textbox("getValue");
    },

    getOrganization: function() {
        return this.organization.textbox("getValue");
    },

    getLocality: function() {
        return this.locality.textbox("getValue");
    },

    getState: function() {
        return this.state.textbox("getValue");
    },

    getCountry: function() {
        return this.country.textbox("getValue");
    },

    getKeyUsage: function() {
        return this.keyUsage.filter(":checked").map(function() { return $(this).val(); }).get();
    },

    getCrlUrl: function() {
        return this.crlUrl.textbox("getValue");
    },

    getSigningKey: function() {
        return this.signWith.is(":checked:not(:disabled)") ? this.signingKey.combobox("getValue") : null;
    },

    setSigningKeys: function(values) {
        this.signingKey.combobox("loadData", values);
    },

    getKeyUsageExtended: function() {
        return this.keyUsageExtended.filter(":checked").map(function() { return $(this).val(); }).get();
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open").dialog("resize", {height: "auto"});
        this.fieldset.form("validate");
        this.fieldset.find("input:first").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 (new jscape.Validator().validateTabs(this.tabs)) {
            this.hide();
            this.listener.onSubmit(this);
        }
    },

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

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

    _adjustKeyLength: function () {
        this.setKeyLengths(jscape.KeyPairAlgorithm.lengthsOf(this.getAlgorithm()));
    }
});

/** @class */
jscape.keystore.GenerateServerKeyCrlСontroller = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyCrlСontroller.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        this.managementService.generateCertificateRevocationList(dialog.getSigningKey(), dialog.getExpires())
                .done($.proxy(function() { this.deferred.resolve(); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function () {
        var dialog = new jscape.keystore.GenerateServerKeyCrlDialog();
        this.managementService.getServerKeys()
                .done(function(keys) { dialog.setSigningKeys($.map(keys, function(key) { return key.name; })); });
        return dialog;
    }
});

/** @class */
jscape.keystore.GenerateServerKeyCrlDialog = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyCrlDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-generatecrl").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=generateserverkeycrlfields]", this.dialog);

        this.signingKey = $("select[name=signingkey]", this.fieldset).combobox({required: true, editable: false, panelHeight: "auto", width: 210});
        this.expires = $("input[name=expires]", this.fieldset).numberspinner({required: true, min: 1, max: 1000, value: 30, width: 80});
    },

    getSigningKey: function() {
        return this.signingKey.combobox("getValue");
    },

    setSigningKeys: function(values) {
        this.signingKey.combobox("loadData", values);
    },

    getExpires: function() {
        return parseInt(this.expires.numberspinner("getValue"));
    },

    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.keystore.VerifyServerKeyRevocationСontroller = Class.extend(
    /** @lends {jscape.keystore.VerifyServerKeyRevocationСontroller.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        this.managementService.verifyCertificateRevocation(dialog.getFile(), "server")
                .done($.proxy(function() { this.deferred.resolve(); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function () {
        return new jscape.keystore.VerifyServerKeyRevocationDialog();
    }
});

/** @class */
jscape.keystore.VerifyServerKeyRevocationDialog = Class.extend(
    /** @lends {jscape.keystore.VerifyServerKeyRevocationDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-verifycrl").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=verifyserverkeycrlfields]", this.dialog);

        this.file = $("input[name=file]", this.fieldset).filebox({required: true, validType: "non_empty", validateOnBlur: true, missingMessage: window.R.string.KEY_MANAGER_ERROR_BAD_FILE, width: "65%"});
    },

    getFile: function () {
        var files = $("#" + this.file.filebox("options").fileboxId)[0].files;
        return files && files.length ? files[0] : null;
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.file.filebox("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.keystore.GenerateServerKeyCsrController = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyCsrController.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        this.managementService.generateServerKeyCSR(this.keyAlias, dialog.getFilename())
                .done($.proxy(function() { this.deferred.resolve(); }, this))
                .fail($.proxy(function() { this.deferred.reject(); }, this))
                .always($.proxy(function() { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _setupDialog: function () {
        return new jscape.keystore.GenerateServerKeyCsrDialog();
    }
});

/** @class */
jscape.keystore.GenerateServerKeyCsrDialog = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyCsrDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-generatecsr").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=generateserverkeycsrfields]", this.dialog);

        this.filename = $("input[name=filename]", this.fieldset).textbox({required: true, validType: "non_empty", missingMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_FILENAME, invalidMessage: window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_BAD_FILENAME, width: "60%"});
    },

    getFilename: function() {
        return this.filename.textbox("getValue");
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.form("validate");
        this.filename.textbox("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.keystore.GenerateServerKeyCertificateController = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyCertificateController.prototype} */
{
    deferred: null,

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

    onSubmit: function(dialog) {
        var data = this._createData(dialog);
        this.managementService.generateServerKeyCertificate(this.keyAlias, data)
                .done($.proxy(function (key) { this.deferred.resolve(key); }, this))
                .fail($.proxy(function () { this.deferred.reject(); }, this))
                .always($.proxy(function () { dialog.destroy(); this.deferred = null; }, this));
    },

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

    _parseSubject: function (data) {
        var values = {};
        var entries = data ? data.split(/,\s*/) : [];
        entries.forEach(function (entry) {
            var parts = entry.split("=");
            if (parts.length == 2) {
                values[parts[0].toUpperCase()] = parts[1];
            }
        });
        return $.extend({CN: "", OU: "", O: "", L: "", ST: "", C: ""}, values);
    },

    _createData: function (dialog) {
        return {
            periodMillis: dialog.getPeriod(),
            commonName: dialog.getCommonName(),
            organizationUnit: dialog.getOrganizationUnit(),
            organization: dialog.getOrganization(),
            locality: dialog.getLocality(),
            state: dialog.getState(),
            country: dialog.getCountry(),
            keyUsage: dialog.getKeyUsage(),
            keyUsageExtended: dialog.getKeyUsageExtended(),
            crlUrl: dialog.getCrlUrl(),
            signingKey: dialog.getSigningKey()
        };
    },

    _setupDialog: function (key) {
        var subject = this._parseSubject(key.certificateSubject);
        var dialog = new jscape.keystore.GenerateServerKeyCertificateDialog();
        dialog.setCommonName(subject.CN);
        dialog.setOrganizationUnit(subject.OU);
        dialog.setOrganization(subject.O);
        dialog.setLocality(subject.L);
        dialog.setState(subject.ST);
        dialog.setCountry(subject.C);
        this.managementService.getServerKeys()
                .done($.proxy(function(keys) { dialog.setSigningKeys($.map(keys, function(key) { return key.name; })); }, this));
        return dialog;
    }
});

/** @class */
jscape.keystore.GenerateServerKeyCertificateDialog = Class.extend(
    /** @lends {jscape.keystore.GenerateServerKeyCertificateDialog.prototype} */
{
    PERIOD_FACTOR: 24 * 60 * 60 * 1000,

    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-serverkey-generatecert").clone().attr("id", "");
        this.dialog.dialog({
            width: 630, 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.tabs = $("div[role=tablist]", this.dialog).tabs({tabPosition: "top", plain: true});
        this.fieldset = $("fieldset[name=generateserverkeycertfields]", this.dialog);

        this.period = $("input[name=period]", this.fieldset).numberspinner({min: 1, max: 10000, value: 365, increment: 10, width: 80});
        this.commonName = $("input[name=commonname]", this.fieldset).textbox({required: true, validType: "non_empty", width: "60%"});
        this.organizationUnit = $("input[name=organizationunit]", this.fieldset).textbox({width: "60%"});
        this.organization = $("input[name=organization]", this.fieldset).textbox({width: "60%"});
        this.locality = $("input[name=locality]", this.fieldset).textbox({width: "60%"});
        this.state = $("input[name=state]", this.fieldset).textbox({width: "60%"});
        this.country = $("input[name=country]", this.fieldset).textbox({width: "60%"});

        this.keyUsage = $("input[name=keyusage]:checkbox", this.fieldset);
        this.keyUsageExtended = $("input[name=keyusageextended]:checkbox", this.fieldset);
        this.crlUrl = $("input[name=crl]", this.fieldset).textbox({validType: "url", width: "75%"});
        this.signWith = $("input[name=signwith]:checkbox")
                .change($.proxy(function () {
                            var enabled = this.signWith.is(":checked:not(:disabled)");
                            this.signingKey.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
                        }, this));
        this.signingKey = $("select[name=serverkeys]", this.fieldset)
                .combobox({required: true, editable: false, disabled: true, width: 200, panelHeight: "auto",
                              onLoadSuccess: $.proxy(function (data) {
                                  if (data.length == 0) {
                                      this.signWith.prop("disabled", true).change();
                                  } else {
                                      this.signingKey.combobox("select", data[0].value);
                                  }
                              }, this)
                          });
    },

    getPeriod: function() {
        return parseInt(this.period.numberspinner("getValue")) * this.PERIOD_FACTOR;
    },

    getCommonName: function() {
        return this.commonName.textbox("getValue");
    },

    setCommonName: function(value) {
        return this.commonName.textbox("setValue", value);
    },

    getOrganizationUnit: function() {
        return this.organizationUnit.textbox("getValue");
    },

    setOrganizationUnit: function(value) {
        return this.organizationUnit.textbox("setValue", value);
    },

    getOrganization: function() {
        return this.organization.textbox("getValue");
    },

    setOrganization: function(value) {
        return this.organization.textbox("setValue", value);
    },

    getLocality: function() {
        return this.locality.textbox("getValue");
    },

    setLocality: function(value) {
        return this.locality.textbox("setValue", value);
    },

    getState: function() {
        return this.state.textbox("getValue");
    },

    setState: function(value) {
        return this.state.textbox("setValue", value);
    },

    getCountry: function() {
        return this.country.textbox("getValue");
    },

    setCountry: function(value) {
        return this.country.textbox("setValue", value);
    },

    getKeyUsage: function() {
        return this.keyUsage.filter(":checked").map(function() { return $(this).val(); }).get();
    },

    getCrlUrl: function() {
        return this.crlUrl.textbox("getValue");
    },

    getSigningKey: function() {
        return this.signWith.is(":checked:not(:disabled)") ? this.signingKey.combobox("getValue") : null;
    },

    setSigningKeys: function(values) {
        this.signingKey.combobox("loadData", values);
    },

    getKeyUsageExtended: function() {
        return this.keyUsageExtended.filter(":checked").map(function() { return $(this).val(); }).get();
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open").dialog("resize", {height: "auto"});
        this.fieldset.form("validate");
        this.commonName.textbox("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 (new jscape.Validator().validateTabs(this.tabs)) {
            this.hide();
            this.listener.onSubmit(this);
        }
    },

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

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

/** @class */
jscape.keystore.RevokeServerKeyController = Class.extend(
    /** @lends {jscape.keystore.RevokeServerKeyController.prototype} */
{
    start: function (managementService, certificate) {
        if (certificate.revoked) {
            return managementService.setServerKeyRevocationStatus(certificate.name, false);
        } else {
            return this._confirmRevoke(certificate.name)
                    .done(function () { return managementService.setServerKeyRevocationStatus(certificate.name, true); })
        }
    },
    _confirmRevoke: function (alias) {
        return jscape.ConfirmDialog.confirm(window.R.string.KEY_MANAGER_REVOKE_CERTIFICATE_TITLE,
                                            window.R.string.KEY_MANAGER_REVOKE_CERTIFICATE_MESSAGE.supplant({0: alias}));
    }
});

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

    start: function (managementService, keyAlias) {
        this.managementService = managementService;
        this.deferred = $.Deferred();
        this._checkKeyUsage(keyAlias)
                .done($.proxy(function (used) {
                    if (used) {
                        this._keyUsedError(keyAlias);
                        this.deferred.reject();
                        this.deferred = null;
                    } else {
                        this._confirmDelete(keyAlias)
                                .done($.proxy(this._deleteConfirmed, this, keyAlias))
                                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
                    }
                }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));

        return this.deferred.promise();
    },

    _checkKeyUsage: function(keyAlias) {
        return this.managementService.keyUsage(keyAlias);
    },

    _deleteConfirmed: function(keyAlias) {
        return this.managementService.deleteServerKey(keyAlias)
                .done($.proxy(function() { this.deferred.resolve(); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
    },

    _confirmDelete: function (keyAlias) {
        return jscape.ConfirmDialog.confirm(window.R.string.KEY_MANAGER_SERVER_KEYS_DELETE_TITLE,
                                            window.R.string.KEY_MANAGER_SERVER_KEYS_DELETE_MESSAGE.supplant({0: keyAlias}));
    },

    _keyUsedError: function (keyAlias) {
        $.messager.alert(window.R.string.DIALOG_TITLE_ERROR,
                         window.R.string.KEY_MANAGER_SERVER_KEYS_ERROR_KEY_USED.supplant({0: keyAlias}),
                         "error");
    }
});

/** @class */
jscape.keystore.ViewServerKeyController = jscape.keystore.ViewKeySummaryController.extend(
    /** @lends {jscape.keystore.ViewServerKeyController.prototype} */
{
    /** @override */
    _loadData: function(alias) {
        return this.managementService.getServerKeyView(alias);
    }
});