jscape.account = jscape.account || {};

/** @class */
jscape.account.OpenPgpKeyEncryptionModule = jscape.ApplicationModule.extend(
    /** @lends {jscape.account.OpenPgpKeyEncryptionModule.prototype} */
{
    onCreate: function() {
        this.controller = new jscape.account.OpenPgpKeyEncryptionController();
    },

    onStart: function() {
        this.controller.start();
    },

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

/** @class */
jscape.account.OpenPgpKeyEncryptionController = Class.extend(
    /** @lends {jscape.account.OpenPgpKeyEncryptionController.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.view = new jscape.account.OpenPgpKeyEncryptionView();

        this.generateController = new jscape.account.GeneratePgpKeyController();
        this.importController = new jscape.account.ImportPgpKeyController();
        this.deleteController = new jscape.account.DeletePgpKeyController();
    },

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

    onResume: function() {
    },

    onGenerateKey: function() {
        this.generateController.start()
                        .done($.proxy(this._fireApplySuccess, this, window.R.string.PGP_ENCRYPTION_SUCCESS_CREATED));
    },

    onImportKey: function() {
        this.importController.start()
                        .done($.proxy(this._fireApplySuccess, this, window.R.string.PGP_ENCRYPTION_SUCCESS_IMPORTED));
    },

    onDeleteKey: function() {
        this.deleteController.start()
                .done($.proxy(this._fireApplySuccess, this, window.R.string.PGP_ENCRYPTION_SUCCESS_DELETED));
    },

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

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

    _fireApplySuccess: function(message) {
        $(document).triggerHandler("broadcast", [message]);
    }
});

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

        this.generateButton = $("a[role=button][name=generate]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$GenerateButton, this)});
        this.importButton = $("a[role=button][name=import]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ImportButton, this)});
        this.deleteButton = $("a[role=button][name=delete]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$DeleteButton, this)});
    },

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

    _onClick$GenerateButton: function() {
        this.listener.onGenerateKey();
    },

    _onClick$ImportButton: function() {
        this.listener.onImportKey();
    },

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

    _adjustState: function() {
    }
});
jscape.account.OpenPgpKeyEncryptionView.LISTENER = {
    onGenerateKey: $.noop,
    onImportKey: $.noop,
    onDeleteKey: $.noop
};

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

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

    onSubmit: function(dialog) {
        jscape.API.generatePgpKey(dialog.getKeyType(),
                                  dialog.getKeyLength(),
                                  dialog.getRealName(),
                                  dialog.getEmail(),
                                  dialog.getFilePassword())
                .done($.proxy(function() { this.deferred.resolve(); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this))
                .always(function() { dialog.destroy(); });
    },

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

    onChangeKeyType: function(dialog) {
        dialog.setKeyLengths(jscape.KeyPairAlgorithm.lengthsOf(dialog.getKeyType()));
    },

    _setupDialog: function() {
        var dialog = new jscape.account.GeneratePgpKeyDialog();
        dialog.setKeyTypes(jscape.KeyPairAlgorithm.values());
        return dialog;
    }
});

/** @class */
jscape.account.GeneratePgpKeyDialog = Class.extend(
    /** @lends {jscape.account.GeneratePgpKeyDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-pgpencrypt-generate").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, handler: $.proxy(this._onSubmit, this)},
                {text: window.R.string.DIALOG_BUTTON_CANCEL, handler: $.proxy(this._onCancel, this)}
            ],
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this)
        }).show();

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

        this.realName = $("input[name=realname]", this.fieldset).textbox({required: true, validType: "pgp_nonempty_name", missingMessage: window.R.string.KEY_MANAGER_PGP_KEYS_ERROR_BAD_NAME, width: 200});
        this.realName.textbox("textbox").on("input", $.proxy(function() { this.email.textbox("validate");}, this));
        this.email = $("input[name=email]", this.fieldset).textbox({validType: "email", invalidMessage: window.R.string.PGP_ENCRYPTION_BAD_EMAIL, width: "50%"});
        this.email.textbox("textbox").on("input", $.proxy(function() { this.realName.textbox("validate");}, this));

        this.keyType = $("select[name=keytype]", this.fieldset).combobox({required: true, editable: false, width: 120, panelHeight: "auto", onChange: $.proxy(this._onChange$KeyType, this)});
        this.keyLength = $("select[name=keylength]", this.fieldset).combobox({required: true, editable: false, width: 120, panelHeight: "auto"});

        var id = $.now().toString(36);
        this.password = $("input[name=password]", this.fieldset).attr("id", id).passwordbox({lastDelay: 0, validateOnBlur: true, width: "50%"});
        this.password.passwordbox("textbox").on("input", $.proxy(function() {
            this.confirmPassword.passwordbox("textbox").validatebox("options").required = this.password.passwordbox("textbox").val().length != 0
        }, this));
        this.confirmPassword = $("input[name=confirmpwd]", this.fieldset).passwordbox({lastDelay: 0, validateOnBlur: true, validType: "file_password_confirm['#" + this.password.attr("id") + "']", missingMessage: window.R.string.PGP_ENCRYPTION_BAD_CONFIRM_PWD, width: "50%"});
    },

    getRealName: function() {
        return this.realName.textbox("getValue");
    },

    getEmail: function() {
        return this.email.textbox("getValue");
    },

    getKeyType: function() {
        return this.keyType.combobox("getValue");
    },

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

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

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

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

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

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

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

    _onChange$KeyType: function() {
        this.listener.onChangeKeyType(this);
    },

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

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

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

    onSubmit: function(dialog) {
        jscape.API.importPgpKey(dialog.getFile())
                .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.account.ImportPgpKeyDialog();
    }
});

/** @class */
jscape.account.ImportPgpKeyDialog = Class.extend(
    /** @lends {jscape.keystore.ImportPgpKeyDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-pgpencrypt-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, handler: $.proxy(this._onSubmit, this)},
                {text: window.R.string.DIALOG_BUTTON_CANCEL, handler: $.proxy(this._onCancel, this)}
            ],
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this)
        }).show();

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

        this.file = $("input[name=file]", this.fieldset).validatebox({required: true, missingMessage: window.R.string.PGP_ENCRYPTION_BAD_KEY_FILE});
    },

    getFile: function() {
        return this.file[0].files[0];
    },

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

    start: function() {
        return this._confirmDelete()
                .then($.proxy(this._deleteConfirmed, this));
    },

    _confirmDelete: function() {
        return jscape.ConfirmDialog.confirm(window.R.string.PGP_ENCRYPTION_CONFIRM_DELETE_TITLE,
                                            window.R.string.PGP_ENCRYPTION_CONFIRM_DELETE_MESSAGE);
    },

    _deleteConfirmed: function() {
        return jscape.API.deletePgpKey();
    }
});