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

/** @class */
jscape.keystore.KeystoreApplication = jscape.Application.extend(
    /** @lends {jscape.keystore.KeystoreApplication.prototype} */
{
    /** @override */
    onReady: function() {
        this._super();
        this._initValidators();
        this.view.show(this);
    },

    /** @override */
    _createView: function() {
        this._super();
        this.view = new jscape.keystore.KeystoreView();
    },

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

    _passwordConfirmed: function (value, params) {
        return value == $(params[0]).val();
    }
});

/** @class */
jscape.keystore.KeystoreModule = jscape.ApplicationModule.extend(
    /** @lends {jscape.keystore.KeystoreModule.prototype} */
{
    onCreate: function() {
        this._super.apply(this, arguments);
    },

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

/** @class */
jscape.keystore.KeystoreView = jscape.DashboardView.extend(
    /** @lends {jscape.keystore.KeystoreView.prototype} */
{
    /** @constructor */
    initialize: function () {
        this._super($("#key-manager[role=tablist]"));

        this.modules.tabs({
            fit: true,
            border: true,
            tabPosition: "top",
            onSelect: $.proxy(this._onSelect$Tab, this)
        });
        this.modules.find("div[role=tablist]")
                .filter(function () { return $(this).parents("div.dialog").length == 0; })
                .each($.proxy(function (_, tablist) {
                          $(tablist).tabs({
                              border: false,
                              onSelect: $.proxy(this._onSelect$Tab, this)
                          });
                      }, this));

        this.modules.find(">div.tabs-header>div.tabs-wrap")
                .hover(
                function () { $(this).css({overflowY: "auto", overflowX: "hidden"}); },
                function () { $(this).css({overflowY: "", overflowX: ""}); }
        );
    },

    /** @override */
    show: function() {
        this._super.apply(this, arguments);
        this.modules.tabs("unselect", 0).tabs("select", 0);
    },

    valid: function() {
        return new jscape.Validator().validateTabs(this.modules);
    }
});

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

        this.alias = $("input[name=alias]", this.fieldset).textbox({required: true});
    },

    getAlias: function() {
        return this.alias.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.ImportPublicKeyTslDialog = Class.extend(
    /** @lends {jscape.keystore.ImportPublicKeyTslDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-pubkey-import-tsl").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=importpubkeyfields]", this.dialog);

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

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

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        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 (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.ExportDialog = Class.extend(
    /** @lends {jscape.keystore.ExportDialog.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[name=exportkeyfields]", this.dialog);

        this.filename = $("input[name=filename]", this.fieldset).textbox({required: true, missingMessage: window.R.string.KEY_MANAGER_EXPORT_KEYS_ERROR_BAD_FILENAME, width: "55%"});
        this.format = $("select[name=format]", this.fieldset).combobox({required: true, editable: false, width: "35%", panelHeight: "auto"});
    },

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

    setFilename: function(value) {
        this.filename.textbox("setValue", value);
    },

    getFormat: function() {
        return this.format.combobox("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.ExportPublicKeyDialog = jscape.keystore.ExportDialog.extend(
    /** @lends {jscape.keystore.ExportPublicKeyDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-publickey-export"));
    }
});

/** @class */
jscape.keystore.ExportPrivateKeyDialog = jscape.keystore.ExportDialog.extend(
    /** @lends {jscape.keystore.ExportPrivateKeyDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-privatekey-export"));

        var passwordId = "pwd_" + Math.random().toString(36).substr(2);
        this.password = $("input[name=password]", this.fieldset).attr("id", passwordId).passwordbox({lastDelay: 0, validateOnBlur: true, width: "50%"});
        this.password.passwordbox("textbox").on("input", $.proxy(function() {
            var enabled = this.password.passwordbox("textbox").val().length != 0;
            this.confirmPassword.passwordbox(enabled ? "enableValidation" : "disableValidation").passwordbox("validate");
        }, this));

        this.confirmPassword = $("input[name=confirmpwd]", this.fieldset).passwordbox({required: true, lastDelay: 0, validateOnBlur: true, validType: "keystore_confirmpwd['#" + passwordId + "']", missingMessage: window.R.string.KEY_MANAGER_EXPORT_KEYS_ERROR_CONFIRM_PASSWORD, width: "50%"});
    },

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

    /** @0verride */
    show: function() {
        this._super.apply(this, arguments);
        this.password.passwordbox("textbox").triggerHandler("input");
    }
});

/** @class */
jscape.keystore.ExportCertificateDialog = jscape.keystore.ExportDialog.extend(
    /** @lends {jscape.keystore.ExportCertificateDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#d-certificate-export"));
    }
});

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

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

        this.view.show(this);
    },

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

    onRefresh: function () {
        return $.when(this.managementService.getServerKeys(),
                      this.managementService.getClientPublicKeys(),
                      this.managementService.getClientCertificates(),
                      this.managementService.getPgpPublicKeys(),
                      this.managementService.getPgpSecretKeys());
    }
});

/** @class */
jscape.keystore.KeyExpirationView = Class.extend(
    /** @lends {jscape.keystore.KeyExpirationView.prototype} */
{
    /** @constructor */
    initialize: function () {
        var initializing = true;

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

        this.data = $("table[role=grid][aria-label=keyexpiryreport]", this.fieldset);
        this.data.propertygrid({
            fit: true,
            fitColumns: true,
            showGroup: true,
            columns: [[
                {field: "name", title: $("thead th:nth-child(1)", this.data).text(), sortable: true, width: 100},
                {field: "expires", title: $("thead th:nth-child(2)", this.data).text(), width: 100, resizable: false, align: "right", formatter: $.proxy(function(_, row) { return this._formatExpirationtionDate(row); }, this), editor: null}
            ]],
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function() { return !initializing; }
        });

        initializing = false;
    },

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

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

    _formatExpirationtionDate: function (key) {
        var time = key && key.hasOwnProperty("certificateEndDate") ? key.certificateEndDate : null;
        return time ? new Date(time).toLocaleString() : window.R.string.KEY_MANAGER_REPORT_DATE_NON_EXPIRING;
    },

    _formatServerKeysGroup: function(keys) {
        return $.map(keys, function (key) { return $.extend({group: window.R.string.KEY_MANAGER_REPORT_GROUP_SERVER_KEYS}, key); });
    },

    _formatClientKeysGroup: function(keys) {
        return $.map(keys, function (key) { return $.extend({group: window.R.string.KEY_MANAGER_REPORT_GROUP_CLIENT_KEYS}, key); });
    },

    _formatPgpKeysGroup: function(keys) {
        return $.map(keys, function (key) { return $.extend({group: window.R.string.KEY_MANAGER_REPORT_GROUP_PGP_KEYS}, key); });
    },

    _onLoad$Data: function (_, success, error) {
        this.listener.onRefresh()
                .then($.proxy(function (serverKeys, clientPublicKeys, clientCertificates, pgpPublicKeys, pgpSecretKeys) {
                          return [].concat(this._formatServerKeysGroup(serverKeys),
                                           this._formatClientKeysGroup(clientPublicKeys.concat(clientCertificates)),
                                           this._formatPgpKeysGroup(pgpPublicKeys.concat(pgpSecretKeys)));
                      }, this))
                .done(success)
                .fail(error);
    }
});
jscape.keystore.KeyExpirationView.LISTENER = {
    onRefresh: $.noop
};

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

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

    onClose: function(dialog) {
        dialog.destroy();
        this.deferred.resolve();
        this.deferred = null;
    },

    _setupDialog: function(alias) {
        var dialog = new jscape.keystore.ViewKeySummaryDialog();
        dialog.setTitle(alias);
        this._loadData(alias).done(function(data) { dialog.setData(data); });
        return dialog;
    },

    _loadData: function(alias) {
        return $.Deferred().resolve([]);
    }
});

/** @class */
jscape.keystore.ViewKeySummaryDialog = Class.extend(
    /** @lends {jscape.keystore.ViewKeySummaryDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-keysummary-view").clone().attr("id", "");
        this.dialog.dialog({
            width: "70%", height: "75%",
            modal: true, resizable: true, closable: true, closed: true,
            buttons: [
                {text: window.R.string.DIALOG_BUTTON_CLOSE || "Close", handler: $.proxy(this._onCancel, this)}
            ],
            onResize: $.proxy(function() { this.data && this.data.propertygrid("resize"); }, this),
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this)
        }).show();

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

        this.data = $("table[role=grid][aria-label=summary]", this.dialog).propertygrid({
            minHeight: 300,
            maxHeight: "90%",
            height: "auto",
            nowrap: false,
            columns: [[
                {
                    field: "name",
                    width: "25%",
                    sortable: true,
                    styler: function () {
                        return "font-weight: bold; border-color: transparent";
                    }
                },
                {
                    field: "value",
                    width: "73%",
                    styler: function () {
                        return "border-color: transparent; overflow-wrap: break-word; word-break: break-word";
                    }
                }
            ]]
        });
    },

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

    setData: function(value) {
        var data = $.map(value || {}, function(val, key) { return {name: key, value: val}; });
        this.data.propertygrid("loadData", data).propertygrid("resize");
    },

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

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

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

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

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