jscape.server = jscape.server || {};

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

    /** @override */
    _createView: function() {
        this._super();
        this.view = new jscape.server.DomainsDashboardView();
    }
});

/** @class */
jscape.server.DomainsDashboardView = jscape.DashboardView.extend(
    /** @lends {jscape.server.DomainsDashboardView.prototype} */
{
    /** @constructor */
    initialize: function () {
        this._super($("#modules[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);
    }
});

/** @class */
jscape.server.DomainsModule = jscape.ApplicationModule.extend(
    /** @lends {jscape.server.DomainsModule.prototype} */
{
    DEFAULT_DELAY: 5 * 1000,

    view: null,
    timerId: null,
    delay: 0,

    onCreate: function(managementService) {
        this._super.apply(this, arguments);

        this.addController = new jscape.domain.NewDomainController();
        this.deleteController = new jscape.server.DeleteDomainController();
        this.statusController = new jscape.server.DomainStatusController();
    },

    onStart: function() {
        this.delay = this.DEFAULT_DELAY;

        if (this.view == null) {
            this.view = new jscape.server.DomainsView();
        }
        this.view.show(this);
        this._poll(0);
    },

    onStop: function() {
        this._stopPoll();
        this.statusController.clear();
    },

    onResume: function() {
        this.view.refresh();
        this.delay = this.DEFAULT_DELAY;
        this._poll(this.delay);
    },

    onPause: function() {
        this._stopPoll();
    },

    onRefresh: function() {
        return this.managementService.getServerStatistics()
                .then(function(data) { return data ? data.domainStatistics : null; })
                .done($.proxy(function () { this.delay = this.DEFAULT_DELAY; }, this))
                .fail($.proxy(function () { this.delay *= 2; }, this));
    },

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

    onEditDomain: function(domain) {
        return this.managementService.editDomain(domain.domainName);
    },

    onDeleteDomain: function (domains) {
        return this.deleteController.start(this.managementService, domains)
                .done($.proxy(this._domainDeleted, this, domains));
    },

    onDomainStartUp: function(domain) {
        return this.managementService.setDomainAutoStart(domain.domainName, !domain.autoStartEnabled)
                .done($.proxy(function() { this._reloadAndSelect(domain.domainName); }, this));
    },

    onStartDomain: function(domains) {
        return $.when($.map(domains, $.proxy(function(domain) { return this.managementService.startDomain(domain.domainName); }, this)))
                .done($.proxy(function() { setTimeout($.proxy(this._reloadAndSelect, this, domains), 500); }, this))
                .fail($.proxy(this._reloadAndSelect, this, []));
    },

    onStopDomain: function(domains) {
        return $.when($.map(domains, $.proxy(function(domain) { return this.managementService.stopDomain(domain.domainName); } , this)))
                .done($.proxy(function() { setTimeout($.proxy(this._reloadAndSelect, this, domains), 500); }, this))
                .fail($.proxy(this._reloadAndSelect, this, []));
    },

    onPauseDomain: function(domains) {
        return $.when($.map(domains, $.proxy(function(domain) { return this.managementService.pauseDomain(domain.domainName); }, this)))
                .done($.proxy(function() { setTimeout($.proxy(this._reloadAndSelect, this, domains), 200); }, this))
                .fail($.proxy(this._reloadAndSelect, this, []));
    },

    onResumeDomain: function(domains) {
        return $.when($.map(domains, $.proxy(function(domain) { return this.managementService.resumeDomain(domain.domainName); }, this)))
                .done($.proxy(function() { setTimeout($.proxy(this._reloadAndSelect, this, domains), 200); }, this))
                .fail($.proxy(this._reloadAndSelect, this, []));
    },

    onDomainStatus: function (domain) {
        return this.statusController.start(this.managementService, domain);
    },

    _poll: function (delay) {
        this._stopPoll();
        this.timerId = setTimeout($.proxy(function () {
            this.timerId = null;
            this.view.refresh();
            this._poll(this.delay);
        }, this), delay || 0);
    },

    _stopPoll: function () {
        if (this.timerId) {
            clearTimeout(this.timerId);
        }
    },

    _domainDeleted: function (domains) {
        var copy = [].concat(this.view.getDomains());
        var index = -1;
        while (domains.length) {
            index = $.inArray(domains.shift(), copy);
            copy.splice(index, 1);
        }
        if (copy.length) {
            index = Math.min(Math.max(0, index), copy.length - 1);
            this._reloadAndSelect(copy[index]);
        }
    },

    _reloadAndSelect: function(domains) {
        this.view.refresh($.proxy(function(entries) {
            entries = $.isArray(entries) ? entries : [entries];
            for (var i = 0; i < entries.length; i++) {
                this.view.selectDomain(entries[i]);
            }
        }, this, domains || []));
    }
});

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

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

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

        this.data = $("table[role=grid][aria-label=serverdomains]", this.fieldset);
        this.data.datagrid({
            fit: true,
            fitColumns: true,
            remoteSort: false,
            ctrlSelect: true,
            idField: "domainName",
            checkOnSelect: true,
            selectOnCheck: true,
            frozenColumns: [[{field: "_ck", checkbox: true}]],
            columns: [[
                {field: "domainName", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_NAME, sortable: true, width: 175},
                {field: "state", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_STATE, sortable: true, width: 90, formatter: $.proxy(function(_, rowData) { return this._formatStatus(rowData); }, this), styler: $.proxy(function(_, rowData) { return this._styleStatus(rowData); }, this)},
                {field: "startup", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_STARTUP, sortable: true, width: 90, align: "center", formatter: $.proxy(function(_, rowData) { return this._formatStartup(rowData); }, this)},
                {field: "currentSessions", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_CURRENT_SESSIONS, sortable: true, width: 110, align: "right"},
                {field: "currentTransfers", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_CURRENT_TRANSFERS, sortable: true, width: 110, align: "right"},
                {field: "totalSessions", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_TOTAL_SESSIONS, sortable: true, width: 110, align: "right"},
                {colspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_UPLOADED},
                {colspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_DOWNLOADED},
                {colspan: 3, title: window.R.string.DOMAINS_TABLE_COLUMN_QUOTA},
                {field: "startDate", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_DATE_START, sortable: true, width: 150, align: "right", formatter: $.proxy(this._formatDate, this)},
                {field: "stopDate", rowspan: 2, title: window.R.string.DOMAINS_TABLE_COLUMN_DATE_STOP, sortable: true, width: 150, align: "right", formatter: $.proxy(this._formatDate, this)}
            ], [
                {field: "bytesUploaded", title: window.R.string.DOMAINS_TABLE_COLUMN_UPLOADED_BYTES, sortable: true, width: 110, align: "right", formatter: $.proxy(this._formatSize, this)},
                {field: "filesUploaded", title: window.R.string.DOMAINS_TABLE_COLUMN_UPLOADED_FILES, sortable: true, width: 100, align: "right"},
                {field: "bytesDownloaded", title: window.R.string.DOMAINS_TABLE_COLUMN_DOWNLOADED_BYTES, sortable: true, width: 110, align: "right", formatter: $.proxy(this._formatSize, this)},
                {field: "filesDownloaded", title: window.R.string.DOMAINS_TABLE_COLUMN_DOWNLOADED_FILES, sortable: true, width: 100, align: "right"},
                {field: "uploadsQuota", title: window.R.string.DOMAINS_TABLE_COLUMN_QUOTA_UPLOADS, sortable: true, width: 140, align: "right", formatter: $.proxy(function(value, rowData) { return this._formatQuota(value, rowData.currentUploadedBytes || 0); }, this)},
                {field: "downloadsQuota", title: window.R.string.DOMAINS_TABLE_COLUMN_QUOTA_DOWNLOADS, sortable: true, width: 150, align: "right", formatter: $.proxy(function(value, rowData) { return this._formatQuota(value, rowData.currentDownloadedBytes || 0); }, this)},
                {field: "transfersQuota", title: window.R.string.DOMAINS_TABLE_COLUMN_QUOTA_TRANSFERS, sortable: true, width: 150, align: "right", formatter: $.proxy(function(value, rowData) { return this._formatQuota(value, (rowData.currentUploadedBytes || 0) + (rowData.currentDownloadedBytes || 0)); }, this)}
            ]],
            onSelect: $.proxy(this._adjustState, this),
            onUnselect: $.proxy(this._adjustState, this),
            onCheckAll: $.proxy(this._adjustState, this),
            onUncheckAll: $.proxy(this._adjustState, this),
            onDblClickRow: $.proxy(this._onClick$EditButton, this),
            loader: $.proxy(this._onLoad$Data, this),
            onBeforeLoad: function() { return !initializing; },
            onLoadSuccess: $.proxy(function() {
                var rows = this.data.datagrid("getRows");
                this.data.datagrid("getPanel").find("div.datagrid-header-check input:checkbox").prop("disabled", rows.length == 0);
                this._adjustState();
            }, this)
        });

        this.startButton = $("a[role=button][name=start]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$StartButton, this)});
        this.stopButton = $("a[role=button][name=stop]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$StopButton, this)});
        this.pauseButton = $("a[role=button][name=pause]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$PauseButton, this)});
        this.resumeButton = $("a[role=button][name=resume]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ResumeButton, this)});

        this.addButton = $("a[role=button][name=add]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$AddButton, this)});
        this.editButton = $("a[role=button][name=edit]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$EditButton, this)});
        this.deleteButton = $("a[role=button][name=delete]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$DeleteButton, this)});
        this.statusButton = $("a[role=button][name=status]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$StatusButton, this)});
        this.startUpButton = $("a[role=button][name=startup]", this.fieldset).linkbutton({disabled: true, toggle: true, onClick: $.proxy(this._onClick$StartUpButton, this)});

        initializing = false;
    },

    getDomains: function() {
        return this.getRecords();
    },

    selectDomain: function(domain) {
        this.selectRecord(domain);
    },

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

    selectItem: function(item) {
        this.data.datagrid("selectRow", this.data.datagrid("getRowIndex", item));
    },

    _formatStatus: function(domain) {
        var status = jscape.DomainStatus.valueOf(domain);
        switch (status) {
            case jscape.DomainStatus.RUNNING:
                return window.R.string.DOMAIN_STATUS_RUNNING;
            case jscape.DomainStatus.PAUSED:
                return window.R.string.DOMAIN_STATUS_PAUSED;
            case jscape.DomainStatus.STOPPED:
                return window.R.string.DOMAIN_STATUS_STOPPED;
            default:
                return "";
        }
    },

    _styleStatus: function(domain) {
        var status = jscape.DomainStatus.valueOf(domain);
        switch (status) {
            case jscape.DomainStatus.RUNNING:
                return "color:green;font-weight:normal";
            case jscape.DomainStatus.PAUSED:
                return "color:black;font-weight:bold";
            case jscape.DomainStatus.STOPPED:
                return "color:red;font-weight:bold";
            default:
                return "color:black;font-weight:normal";
        }
    },

    _formatStartup: function(domain) {
        return "<input type=\"checkbox\"" + (!!domain.autoStartEnabled ? " checked=\"checked\"" : "") +" onclick=\"return false\"/>";
    },

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

    _formatQuota: function(total, used) {
        return total ? window.R.string.DOMAINS_TABLE_QUOTA_PATTERN.supplant({0: this._formatSize(used), 1: this._formatSize(total)}) : "";
    },

    _formatSize: function(value) {
        return jscape.SizeFormat.format(value);
    },

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

    _onClick$StartButton: function() {
        this.startButton.linkbutton("disable");
        this.listener.onStartDomain(this.selection);
    },

    _onClick$StopButton: function() {
        this.stopButton.linkbutton("disable");
        this.listener.onStopDomain(this.selection);
    },

    _onClick$PauseButton: function() {
        this.pauseButton.linkbutton("disable");
        this.listener.onPauseDomain(this.selection);
    },

    _onClick$ResumeButton: function() {
        this.resumeButton.linkbutton("disable");
        this.listener.onResumeDomain(this.selection);
    },

    _onClick$AddButton: function() {
        this.addButton.linkbutton("disable");
        this.listener.onAddDomain()
                .always($.proxy(function() { this.addButton.linkbutton("enable"); }, this));
    },

    _onClick$EditButton: function() {
        this.editButton.linkbutton("disable");
        this.listener.onEditDomain(this.selection[0])
                .always($.proxy(function() { this.editButton.linkbutton("enable"); }, this));
    },

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

    _onClick$StatusButton: function() {
        this.statusButton.linkbutton("disable");
        this.listener.onDomainStatus(this.selection[0])
                .always($.proxy(function() { this.statusButton.linkbutton("enable"); }, this));
    },

    _onClick$StartUpButton: function() {
        if (this.startUpButton.length) {
            this.startUpButton.linkbutton("disable");
            this.listener.onDomainStartUp(this.selection[0])
                    .always($.proxy(function() { this.startUpButton.linkbutton("enable"); }, this));
        }
    },

    _adjustState: function() {
        this.selection = this.data.datagrid("getSelections");

        this.startButton.linkbutton(this.selection.length != 0 && this._domainStateIs(jscape.DomainStatus.STOPPED, this.selection) ? "enable" : "disable");
        this.stopButton.linkbutton(this.selection.length != 0 && !this._domainStateIs(jscape.DomainStatus.STOPPED, this.selection) ? "enable" : "disable");
        this.pauseButton.linkbutton(this.selection.length != 0 && this._domainStateIs(jscape.DomainStatus.RUNNING, this.selection) ? "enable" : "disable");
        this.resumeButton.linkbutton(this.selection.length != 0 && this._domainStateIs(jscape.DomainStatus.PAUSED, this.selection) ? "enable" : "disable");
        this.editButton.linkbutton(this.selection.length == 1 ? "enable" : "disable");
        this.deleteButton.linkbutton(this.selection.length != 0 ? "enable" : "disable");
        this.statusButton.linkbutton(this.selection.length == 1 ? "enable" : "disable");
        if (this.startUpButton.length) {
            if (this.selection.length == 1) {
                this.startUpButton.linkbutton("enable").linkbutton(this.selection[0].autoStartEnabled ? "select" : "unselect");
            } else {
                this.startUpButton.linkbutton("disable");
            }
        }
    },

    _domainStateIs: function(state, rows) {
        var ret = rows.length != 0;
        for (var i = 0; i < rows.length; i++) {
            ret &= (state === jscape.DomainStatus.valueOf(rows[i]));
        }
        return ret;
    }
});
jscape.server.DomainsView.LISTENER = {
    onAddDomain: $.noop,
    onEditDomain: $.noop,
    onDeleteDomain: $.noop,
    onStartDomain: $.noop,
    onStopDomain: $.noop,
    onPauseDomain: $.noop,
    onResumeDomain: $.noop,
    onDomainStatus: $.noop,
    onDomainStartUp: $.noop
};

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

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

    _confirmDelete: function(domains) {
        var names = $.map(domains, function(domain) { return domain.domainName; });
        return jscape.ConfirmDialog.confirm(window.R.string.DOMAINS_CONFIRM_DELETE_TITLE,
                                            window.R.string.DOMAINS_CONFIRM_DELETE_MESSAGE.supplant({0: names.join(", ")}));
    },

    _deleteConfirmed: function(domains) {
        $.when.apply(jQuery, $.map(domains, $.proxy(function(domain) { return this.managementService.deleteDomain(domain.domainName); }, this)))
                .done($.proxy(function () { this.deferred.resolve(domains); this.deferred = null; }, this))
                .fail($.proxy(function () { this.deferred.reject(); this.deferred = null; }, this))
    }
});

/** @class */
jscape.server.DomainStatusController = Class.extend(
    /** @lends {jscape.server.DomainStatusController.prototype} */
{
    DEFAULT_DELAY: 10 * 1000,

    deferred: null,
    timerId: null,
    delay: null,
    statistics: null,
    buffers: null,
    logBuffer: null,
    eventLogPaused: false,

    /** @constructor */
    initialize: function () {
        this.buffers = {};
    },

    start: function(managementService, domain) {
        this.deferred = $.Deferred();
        this.delay = this.DEFAULT_DELAY;
        this.statistics = new jscape.DomainState();
        this.managementService = managementService;
        this.domainName = domain.domainName;
        if (!this.buffers[this.domainName]) {
            this.buffers[this.domainName] = new jscape.server.LogBuffer();
        }
        this.logBuffer = this.buffers[this.domainName];

        this._setupDialog(domain).show(this);
        this.sessionsView.show({onRefresh: $.proxy(this.onRefreshSessions, this), onCloseConnection: $.proxy(this.onCloseConnection, this)});
        this.eventLogView.show({onRefresh: $.proxy(this.onRefreshEventLog, this), onPause: $.proxy(this.onPauseEventLog, this), onResume: $.proxy(this.onResumeEventLog, this)});

        this._poll(0);
        return this.deferred.promise();
    },

    clear: function() {
        for (var i in this.buffers) {
            this.buffers[i].clear();
            delete this.buffers[i];
        }
        this.buffers = {};
    },

    onStartDomain: function (dialog) {
        return this.managementService.startDomain(this.domainName)
                .done($.proxy(function () { this._poll(0); }, this));
    },

    onStopDomain: function (dialog) {
        return this.managementService.stopDomain(this.domainName)
                .done($.proxy(function () { this._poll(0); }, this));
    },

    onPauseDomain: function (dialog) {
        return this.managementService.pauseDomain(this.domainName)
                .done($.proxy(function () { this._poll(0); }, this));
    },

    onResumeDomain: function (dialog) {
        return this.managementService.resumeDomain(this.domainName)
                .done($.proxy(function () { this._poll(0); }, this));
    },

    onRefresh: function () {
        return $.Deferred().resolve(this.statistics).promise();
    },

    onRefreshSessions: function() {
        return $.Deferred().resolve(this.statistics.connectionStatistics).promise();
    },

    onCloseConnection: function(session) {
        var controller = new jscape.domain.CloseSessionController();
        controller.start(this.managementService, this.domainName, session)
                .done($.proxy(function() { this._poll(0); }, this));
    },

    onRefreshEventLog: function() {
        if (this.eventLogPaused) {
            return $.Deferred().reject().promise();
        }
        this.logBuffer.setLength(this.eventLogView.getMaxRecords());
        return $.Deferred().resolve(this.logBuffer.toString()).promise();
    },

    onPauseEventLog: function () {
        this.eventLogPaused = true;
    },

    onResumeEventLog: function () {
        this.eventLogPaused = false;
        this.eventLogView.refresh();
    },

    onClose: function (dialog) {
        this._stopPoll();
        dialog.destroy();
        this.deferred.resolve();
        this.deferred = null;
        this.sessionsView = null;
        this.eventLogView = null;
        this.managementService = null;
        this.domainName = null;
        this.logBuffer = null;
    },

    _poll: function(delay) {
        this._stopPoll();
        this.timerId = setTimeout($.proxy(function () {
            this.timerId = null;
            this.managementService.getDomainStatistics(this.domainName)
                    .done($.proxy(function (data) {
                              this.statistics = data;
                              this.logBuffer.append(data.log || "");
                              this.delay = this.DEFAULT_DELAY;
                              this._poll(this.delay);
                          }, this))
                    .done($.proxy(function () {
                              this.dialog.refresh();
                              this.eventLogView.refresh();
                              this.sessionsView.refresh();
                          }, this))
                    .fail($.proxy(function (data) {
                              if (403 == data.status) {
                                  this._stopPoll();
                                  this.onClose(this.dialog);
                                  this._showNoPermissionsMessage((data.status || "") + " " + data.statusText);
                              } else {
                                  this.delay *= 2;
                                  this._poll(this.delay);
                              }
                          }, this));
        }, this), delay || 0);
    },

    _stopPoll: function() {
        if (this.timerId) {
            clearInterval(this.timerId);
            this.timerId = null;
        }
    },

    _showNoPermissionsMessage: function(title) {
        $.messager.alert(title, window.R.string.NO_PERMISSIONS, "error");
    },

    _setupDialog: function(domain) {
        var dialog = new jscape.server.DomainStatusDialog();
        dialog.setDomainName(domain.domainName);
        dialog.setStatus(jscape.DomainStatus.valueOf(domain));

        try {
            this.sessionsView = new jscape.domain.SessionsView(dialog.container());
            this.eventLogView = new jscape.server.EventLogView(dialog.container());
            this.dialog = dialog;
            return dialog;
        } catch (e) {
            dialog.destroy();
            throw e;
        }
    }
});

/** @class */
jscape.server.LogBuffer = Class.extend(
    /** @lends {jscape.server.prototype} */
{
    DEFAULT_MAX_RECORDS: 1000,
    EOL: "\r\n",

    data: null,
    maxRecords: null,

    /** @constructor */
    initialize: function(a) {
        this.data = "";
        this.setLength(a);
    },

    length: function() {
        return this.data.length;
    },

    setLength: function(value) {
        this.maxRecords = parseInt(value) || this.DEFAULT_MAX_RECORDS;
        this._removeSuperfluousRecords();
        return this;
    },

    clear: function () {
        this.data = "";
        return this;
    },

    append: function(text) {
        if (text) {
            this.data += text;
            this._removeSuperfluousRecords();
        }
        return this;
    },

    toString: function() {
        this._removeSuperfluousRecords();
        return this.data;
    },

    _removeSuperfluousRecords: function() {
        var index = this._indexOf(this.maxRecords);
        if (index > -1) {
            this.data = this.data.substring(index + this.EOL.length);
        }
    },

    _indexOf: function(recordsCount) {
        var index = this.data.length - 1;
        while (--recordsCount >= 0 && index > -1) {
            index = this.data.lastIndexOf(this.EOL, index - this.EOL.length);
        }
        return index;
    }
});

/** @class */
jscape.server.EventLogView = Class.extend(
    /** @lends {jscape.server.EventLogView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this.fieldset = $("fieldset[name=eventlogfields]", container);

        this.maxRecords = $("input[name=maxlogrecords]", this.fieldset).numberspinner({required: true, min: 10, max: 1000, increment: 10, value: 1000, width: 100, onChange: $.proxy(this._onChange$MaxRecords, this)});
        this.records = $("textarea[name=eventlogs]", this.fieldset).css({width: "77em", height: "22em"}).prop("readonly", true);

        this.pauseButton = $("a[role=button][name=pauselog]", this.fieldset).linkbutton({toggle: true, onClick: $.proxy(this._onClick$PauseButton, this)});
    },

    getMaxRecords: function() {
        return parseInt(this.maxRecords.numberspinner("getValue"));
    },

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

    refresh: function() {
        this.listener.onRefresh()
                .done($.proxy(function(data) { this.records.val(data); }, this));
    },

    _onChange$MaxRecords: function(newValue, oldValue) {
        if (newValue < oldValue) {
            this.refresh();
        }
    },

    _onClick$PauseButton: function() {
        this._adjustPauseButtonText();
        if (this.pauseButton.linkbutton("options").selected) {
            this.listener.onPause();
        } else {
            this.listener.onResume();
        }
    },

    _adjustPauseButtonText: function () {
        var text = this.pauseButton.text();
        this.pauseButton.html(this.pauseButton.html().replace(text, this.pauseButton.data("toggle-text")));
        this.pauseButton.data("toggle-text", text);
    }
});
jscape.server.EventLogView.LISTENER = {
    onRefresh: $.noop,
    onPause: $.noop,
    onResume: $.noop
};

/** @class */
jscape.server.DomainStatusDialog = Class.extend(
    /** @lends {jscape.server.DomainStatusDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this.dialog = $("#d-domain-status").clone().attr("id", "");
        this.dialog.dialog({
            width: 980, height: "auto",
            modal: true, resizable: false, closable: true, closed: true,
            buttons: [
                {text: window.R.string.DIALOG_BUTTON_CLOSE || "Close", handler: $.proxy(this._onCancel, this)}
            ],
            onClose: $.proxy(function () {if (!this.closing) { this._onCancel(); }}, this)
        }).show();

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

        this.fieldset = $("fieldset[name=domainstatusfields]", this.dialog);
        this.tabs = $("div[role=tablist]", this.fieldset);
        this.tabs.tabs({tabPosition: "top", plain: true, width: 920, height: 470});

        this.startButton = $("a[role=button][name=startdomain]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$StartButton, this)});
        this.stopButton = $("a[role=button][name=stopdomain]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$StopButton, this)});
        this.pauseButton = $("a[role=button][name=pausedomain]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$PauseButton, this)});
        this.resumeButton = $("a[role=button][name=resumedomain]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$ResumeButton, this)});

        this.status = $("dd[aria-label=status]", this.fieldset);
        this.startDate = $("dd[aria-label=startdate]", this.fieldset);
        this.stopDate = $("dd[aria-label=stopdate]", this.fieldset);
        this.connections = $("dd[aria-label=connections]", this.fieldset);
        this.transfers = $("dd[aria-label=transfers]", this.fieldset);
        this.totalConnections = $("dd[aria-label=totalconnections]", this.fieldset);
        this.sessionUploaded = $("dd[aria-label=sessionuploaded]", this.fieldset);
        this.sessionDownloaded = $("dd[aria-label=sessiondownloaded]", this.fieldset);
        this.uploadsQuota = $("dd[aria-label=uploadsquota]", this.fieldset);
        this.downloadsQuota = $("dd[aria-label=downloadsquota]", this.fieldset);
        this.transfersQuota = $("dd[aria-label=transfersquota]", this.fieldset);
    },

    container: function() {
        return this.dialog;
    },

    setDomainName: function(value) {
        this.domainName = value || "";
        this.dialog.dialog("setTitle", this.title.supplant({0: this.domainName, 1: window.R.string.DOMAIN_MESSAGE_LOADING}));
    },

    setStatus: function(value) {
        this.dialog.dialog("setTitle", this.title.supplant({0: this.domainName, 1: window.R.string["DOMAIN_STATUS_" + value.toUpperCase()]}));
        this._adjustButtonsState(value);
    },

    show: function (listener) {
        this.listener = listener;
        this.dialog.dialog("center").dialog("open");
        this.fieldset.find("textarea[name=eventlogs]").css("width", "63em");
        this._adjustButtonsState(null);
    },

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

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

    refresh: function () {
        this.listener.onRefresh(this)
                .done($.proxy(function (statistics) {
                          this._statistics(statistics);
                          this.setStatus(jscape.DomainStatus.valueOf(statistics));
                      }, this))
                .fail($.proxy(function () { this._statistics(null); }, this));
    },

    _statistics: function(stats) {
        if (stats) {
            this.status.text(this._formatStatus(stats));
            this.startDate.text(this._formatDate(stats.startDate));
            this.stopDate.text(this._formatDate(stats.stopDate));
            this.connections.text(stats.currentSessions);
            this.transfers.text(stats.currentTransfers);
            this.totalConnections.text(stats.totalSessions);
            this.sessionUploaded.text(this._formatTransfers(stats.bytesUploaded, stats.filesUploaded));
            this.sessionDownloaded.text(this._formatTransfers(stats.bytesDownloaded, stats.filesDownloaded));
            this.uploadsQuota.text(this._formatQuota(stats.uploadsQuota, stats.currentUploadedBytes));
            this.downloadsQuota.text(this._formatQuota(stats.downloadsQuota, stats.currentDownloadedBytes));
            this.transfersQuota.text(this._formatQuota(stats.transfersQuota, stats.currentTransferredBytes));
        } else {
            $.each([
                       this.status, this.startDate, this.stopDate, this.connections, this.transfers, this.totalConnections,
                       this.sessionUploaded, this.sessionDownloaded, this.uploadsQuota, this.downloadsQuota, this.transfersQuota
                   ], function (_, entry) { entry.text("-"); });
        }
    },

    _formatStatus: function(value) {
        return window.R.string["DOMAIN_STATUS_" + jscape.DomainStatus.valueOf(value).toUpperCase()];
    },

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

    _formatTransfers: function(bytes, files) {
        return window.R.string.STATISTICS_TEMPLATE_TRANSFERS.supplant({0: jscape.SizeFormat.format(bytes), 1: files});
    },

    _formatQuota: function(quota, bytes) {
        return quota ? window.R.string.STATISTICS_TEMPLATE_QUOTA.supplant({0: jscape.SizeFormat.format(bytes), 1: jscape.SizeFormat.format(quota)}) : "-";
    },

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

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

    _onClick$StartButton: function() {
        this.listener.onStartDomain(this);
    },

    _onClick$StopButton: function() {
        this.listener.onStopDomain(this);
    },

    _onClick$PauseButton: function() {
        this.listener.onPauseDomain(this);
    },

    _onClick$ResumeButton: function() {
        this.listener.onResumeDomain(this);
    },

    _adjustButtonsState: function (status) {
        this.startButton.linkbutton(jscape.DomainStatus.STOPPED == status ? "enable" : "disable");
        this.stopButton.linkbutton(jscape.DomainStatus.STOPPED != status ? "enable" : "disable");
        this.pauseButton.linkbutton(jscape.DomainStatus.RUNNING == status ? "enable" : "disable");
        this.resumeButton.linkbutton(jscape.DomainStatus.PAUSED == status ? "enable" : "disable");
    }
});
jscape.server.DomainStatusDialog.LISTENER = {
    onStartDomain: $.noop,
    onStopDomain: $.noop,
    onPauseDomain: $.noop,
    onResumeDomain: $.noop,
    onRefresh: $.noop,
    onClose: $.noop
};