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

/** @class */
jscape.AdHocTransferInfo = Class.extend(
    /** @lends {jscape.AdHocTransferInfo.prototype} */
{
    /** @constructor */
    initialize: function(a, b, c, d, e, f, g, h, i, j, k) {
        this.id = a || "";
        this.sender = b || "";
        this.recipient = c || "";
        this.ccRecipients = d || [];
        this.bccRecipients = e || [];
        this.subject = f || "";
        this.message = g || "";
        this.transferObjects = h || [];
        this.dispatchTime = parseInt(i) || 0;
        this.downloads = parseInt(j) || 0;
        this.status = k || jscape.AdHocTransferInfo.Status.ACTIVE;
    }
});
jscape.AdHocTransferInfo.fromJSON = function(data) {
    return data ? new jscape.AdHocTransferInfo(data.id, data.sender, data.recipient, data.ccRecipients, data.bccRecipients, data.subject, data.message, $.map(data.transferObjects || [], jscape.AdHocTransferInfo.Entry.fromJSON), data.dispatchTime, data.downloads, data.status) : null;
};
/** @class */
jscape.AdHocTransferInfo.Entry = Class.extend(
    /** @lends {jscape.AdHocTransferInfo.Entry.prototype} */
{
    /** @constructor */
    initialize: function(id, name, path, expires, downloads, status) {
        this.id = id || "";
        this.name = name || "";
        this.path = path || "";
        this.expires = parseInt(expires) || null;
        this.downloads = parseInt(downloads) || 0;
        this.status = status || jscape.AdHocTransferInfo.Status.ACTIVE;
    }
});
jscape.AdHocTransferInfo.Entry.fromJSON = function(data) {
    return data ? new jscape.AdHocTransferInfo.Entry(data.id, data.name, data.path, data.expires, data.downloads, data.status) : null;
};

jscape.AdHocTransferInfo.Status = {ACTIVE: "ACTIVE", REVOKED: "REVOKED", EXPIRED: "EXPIRED"};


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

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

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

/** @class */
jscape.account.AdHocTransfersController = jscape.ui.DatagridController.extend(
    /** @lends {jscape.account.AdHocTransferController.prototype} */
{
    view: null,

    /** @constructor */
    initialize: function() {
        this.view = new jscape.account.AdHocTransfersView();

        this.extendController = new jscape.account.ExtendAdHocTransferController();
        this.revokeController = new jscape.account.RevokeAdHocTransferController();
        this.viewController = new jscape.account.ViewAdHocTransferController();
    },

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

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

    onRefresh: function (params) {
        params = jscape.Page.requestParameters(params);
        return jscape.API.listAdhocTransfers(params.startIndex, params.count, params.query)
                .then(jscape.Page.datagridFormatter());
    },

    onExtend: function(transfers) {
        this.extendController.start(transfers)
                .done($.proxy(this._transferExtended, this));
    },

    onRevoke: function(transfers) {
        this.revokeController.start(transfers)
                .done($.proxy(this._transferRevoked, this));
    },

    onView: function(transfer) {
        this.viewController.start(transfer)
                .done($.proxy(function() { this.view.refresh(); }, this));
    },

    _transferRevoked: function(transfers) {
        this._reloadAndSelect(transfers)
    },

    _transferExtended: function(transfer) {
        this._reloadAndSelect(transfer);
    }
});

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

    /** @constructor */
    initialize: function() {
        var initializing = true;
        this.fieldset = $("fieldset[name=adhoctransferfields]");

        this.data = $("table[role=grid][aria-label=adhoctransfers]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            ctrlSelect: true,
            pagination: true,
            search: true,
            remoteSearch: true,
            remoteSort: true,
            sortName: "date",
            sortOrder: "desc",
            idField: "id",
            columns: [[
                {field: "date", title: $("thead th:nth-child(1)", this.data).text(), width: 100, sortable: true, formatter: $.proxy(function(_, data) { return this._formatDate(data.dispatchTime);}, this), finder: "datebox"},
                {field: "subject", title: $("thead th:nth-child(2)", this.data).text(), width: 80, sortable: true},
                {field: "recipient", title: $("thead th:nth-child(3)", this.data).text(), width: 100, sortable: true},
                {field: "files", title: $("thead th:nth-child(4)", this.data).text(), width: 80, sortable: true, formatter: function(_, data) { return data.transferObjects.length; }},
                {field: "downloads", title: $("thead th:nth-child(5)", this.data).text(), width: 80, sortable: true},
                {field: "status", title: $("thead th:nth-child(6)", this.data).text(), width: 80, sortable: true, formatter: $.proxy(this._formatStatus, this), styler: $.proxy(this._styleStatus, this), finder: {type: "combobox", options: {panelHeight: "auto", data: $.map([jscape.AdHocTransferInfo.Status.ACTIVE, jscape.AdHocTransferInfo.Status.REVOKED, jscape.AdHocTransferInfo.Status.EXPIRED], $.proxy(function (entry) { return {text: this._formatStatus(entry), value: entry}; }, this))}}}
            ]],
            onSelect: $.proxy(this._adjustState, this),
            onUnselect: $.proxy(this._adjustState, this),
            onDblClickRow: $.proxy(this._onClick$ViewButton, this),
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function() { return !initializing; },
            onLoadSuccess: $.proxy(this._adjustState, this)
        });

        this.revokeButton = $("a[role=button][name=revoke]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$RevokeButton, this)});
        this.extendButton = $("a[role=button][name=extend]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ExtendButton, this)});
        this.viewButton = $("a[role=button][name=view]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ViewButton, this)});

        initializing = false;
    },

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

    _formatDate: function(value) {
        return $.isNumeric(value) ? new Date(value).toLocaleString() : "";
    },

    _formatStatus: function(value) {
        return window.R.string[("ADHOC_TRANSFER_STATUS_" + value).toUpperCase()] || String(value || "").escapeXml();
    },

    _styleStatus: function(value) {
        switch (value) {
            case jscape.AdHocTransferInfo.Status.ACTIVE:
                return "color:green";
            case jscape.AdHocTransferInfo.Status.EXPIRED:
                return "color:brown";
            case jscape.AdHocTransferInfo.Status.REVOKED:
                return "color:red";
            default:
                return "color:#000";
        }
    },

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

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

    _onClick$ExtendButton: function() {
        this.listener.onExtend(this.selection);
    },

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

    _adjustState: function () {
        this.selection = this.data.datagrid("getSelections");
        this.extendButton.linkbutton(this.selection.length != 0 ? "enable" : "disable");
        this.revokeButton.linkbutton(this.selection.length != 0 && $.grep(this.selection, function(entry) { return jscape.AdHocTransferInfo.Status.REVOKED == entry.status; }).length == 0 ? "enable" : "disable");
        this.viewButton.linkbutton(this.selection.length == 1 ? "enable" : "disable");
    }
});
jscape.account.AdHocTransfersView.LISTENER = {
    onRefresh: $.noop,
    onExtend: $.noop,
    onRevoke: $.noop,
    onView: $.noop
};

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

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

    onRefresh: function () {
        return jscape.API.getAdHocTransfer(this.transfer.id);
    },

    onExtend: function(objects, dialog) {
        var controller = new jscape.account.ExtendAdHocTransferController();
        return controller.start([this.transfer], $.map(objects, function(object) { return object.id; }))
                .done($.proxy(function() { dialog.refresh(); }, this));
    },

    onRevoke: function(objects, dialog) {
        var controller = new jscape.account.RevokeAdHocTransferController();
        return controller.start([this.transfer], $.map(objects, function(object) { return object.id; }))
                .done($.proxy(function() { dialog.refresh(); }, this));
    },

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

    _setupDialog: function() {
        return new jscape.account.ViewAdHocTransferDialog();
    }
});

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

        this.dialog = $("#d-adhoctransfer-view").clone().attr("id", "");
        this.dialog.dialog({
            width: 880, height: "auto",
            modal: true, resizable: false, closable: true, closed: true,
            buttons: [{text: window.R.string.DIALOG_BUTTON_CLOSE || "Close", handler: $.proxy(this._onClose, this)}],
            onClose: $.proxy(function () {if (!this.closing) { this._onClose(); }}, this)
        }).show();

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

        this.sender = $("span[aria-label=sender]", this.fieldset);
        this.date = $("span[aria-label=date]", this.fieldset);
        this.recipient = $("span[aria-label=recipient]", this.fieldset);
        this.cc = $("span[aria-label=cc]", this.fieldset);
        this.bcc = $("span[aria-label=bcc]", this.fieldset);
        this.message = $("span[aria-label=message]", this.fieldset);

        this.data = $("table[role=grid][aria-label=transferobjects]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            remoteSearch: true,
            remoteSort: true,
            sortName: "name",
            sortOrder: "desc",
            idField: "id",
            columns: [[
                    {field: "name", title: $("thead th:nth-child(1)", this.data).text(), width: 80, sortable: true},
                    {field: "path", title: $("thead th:nth-child(2)", this.data).text(), width: 170, sortable: true},
                    {field: "downloads", title: $("thead th:nth-child(3)", this.data).text(), width: 50, sortable: true},
                    {field: "expires", title: $("thead th:nth-child(4)", this.data).text(), width: 100, sortable: true, formatter: $.proxy(function(_, data) { return this._formatDate(data.expires); }, this)},
                    {field: "status", title: $("thead th:nth-child(5)", this.data).text(), width: 50, sortable: true, formatter: $.proxy(this._formatStatus, this), styler: $.proxy(this._styleStatus, this), finder: {type: "combobox", options: {panelHeight: "auto", data: $.map([jscape.AdHocTransferInfo.Status.ACTIVE, jscape.AdHocTransferInfo.Status.REVOKED, jscape.AdHocTransferInfo.Status.EXPIRED], $.proxy(function (entry) { return {text: this._formatStatus(entry), value: entry}; }, this))}}}
            ]],
            onSelect: $.proxy(this._adjustState, this),
            onUnselect: $.proxy(this._adjustState, this),
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function() { return !initializing; },
            onLoadSuccess: $.proxy(this._adjustState, this)
        });

        this.revokeButton = $("a[role=button][name=revoke]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$RevokeButton, this)});
        this.extendButton = $("a[role=button][name=extend]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ExtendButton, this)});

        initializing = false;
    },

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

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

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

    _formatDate: function(value) {
        return $.isNumeric(value) ? new Date(value).toLocaleString() : "";
    },

    _formatStatus: function(value) {
        return window.R.string[("ADHOC_TRANSFER_STATUS_" + value).toUpperCase()] || String(value || "").escapeXml();
    },

    _styleStatus: function(value) {
        switch (value) {
            case jscape.AdHocTransferInfo.Status.ACTIVE:
                return "color:green";
            case jscape.AdHocTransferInfo.Status.EXPIRED:
                return "color:brown";
            case jscape.AdHocTransferInfo.Status.REVOKED:
                return "color:red";
            default:
                return "color:#000";
        }
    },

    _onLoad$Data: function (params, success, error) {
        this.listener.onRefresh(params)
                .then($.proxy(function(data) {
                                 if (data) {
                                     this._loadData(data);
                                     return data.transferObjects;
                                 }
                                 return [];
                              }, this))
                .done(success)
                .fail(error);
    },

    _loadData: function (data) {
        this.sender.text(data.sender);
        this.date.text(this._formatDate(data.dispatchTime));
        this.recipient.text(data.recipient);
        this.cc.text(data.ccRecipients.join(", "));
        this.bcc.text(data.bccRecipients.join(", "));
        this.message.text(data.message);
    },

    _onClick$RevokeButton: function() {
        this.revokeButton.linkbutton("disable");
        this.listener.onRevoke(this.selection, this)
                .always($.proxy(this._adjustState, this));
    },

    _onClick$ExtendButton: function() {
        this.extendButton.linkbutton("disable");
        this.listener.onExtend(this.selection, this)
                .always($.proxy(this._adjustState, this));
    },

    _adjustState: function () {
        this.selection = this.data.datagrid("getSelections");
        this.extendButton.linkbutton(this.selection.length != 0 ? "enable" : "disable");
        this.revokeButton.linkbutton(this.selection.length != 0 && $.grep(this.selection, function(entry) { return jscape.AdHocTransferInfo.Status.REVOKED == entry.status; }).length == 0 ? "enable" : "disable");
    },

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

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

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

    start: function(transfers, transferObjectIds) {
        this.transfers = transfers;
        this.transferObjectIds = transferObjectIds || [];
        this.deferred = $.Deferred();
        this._setupDialog(transfers).show(this);
        return this.deferred.promise();
    },

    onSubmit: function(dialog) {
        var expires = dialog.getDate().getTime();
        dialog.destroy();

        $.when.apply(jQuery, $.map(this.transfers, $.proxy(function(transfer) { return jscape.API.extendAdHocTransfer(transfer.id, expires, this.transferObjectIds); }, this)))
                .done($.proxy(function() { this.deferred.resolve(this.transfers); this.deferred = null; }, this))
                .fail($.proxy(function() { this.deferred.reject(); this.deferred = null; }, this));
    },

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

    _setupDialog: function() {
        var dialog = new jscape.account.ExtendAdHocTransferDialog();
        var date = new Date();
        date.setDate(date.getDate() + 7);
        dialog.setDate(date);
        return dialog;
    }
});

/** @class */
jscape.account.ExtendAdHocTransferDialog = Class.extend(
    /** @lends {jscape.account.ExtendAdHocTransferDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-adhoctransfer-extend").clone().attr("id", "");
        this.dialog.dialog({
            width: 430, 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=adhoctransferextendfields]", this.dialog);

        this.date = $("input[name=date]", this.fieldset).datebox({required: true, width: 150});
        this.date.datebox("calendar").calendar({validator: function(date) {
            return new Date().getTime() < date.getTime();
        }});
    },

    getDate: function() {
        var text = this.date.datebox("getValue");
        return this.date.datebox("options").parser(text);
    },

    setDate: function(value) {
        var text = this.date.datebox("options").formatter(value);
        this.date.datebox("setValue", text);
    },

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

    start: function(transfers, transferObjectIds) {
        return this._confirmRevoke(transfers)
                .then($.proxy(this._revokeConfirmed, this, transfers, transferObjectIds));
    },

    _confirmRevoke: function(transfers) {
        return jscape.ConfirmDialog.confirm(window.R.string.ADHOC_TRANSFER_REVOKE_TITLE,
                                            window.R.string.ADHOC_TRANSFER_REVOKE_MESSAGE);
    },

    _revokeConfirmed: function(transfers, transferObjectIds) {
        return $.when.apply(jQuery, $.map(transfers, function(transfer) { return jscape.API.revokeAdHocTransfer(transfer.id, transferObjectIds); }));
    }
});