jscape.domain = jscape.domain || {};

/** @class */
jscape.domain.LogBuffer = Class.extend(
    /** @lends {jscape.LogBuffer.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.LogConfiguration = Class.extend(
    /** @lends {jscape.LogConfiguration.prototype} */
{
    /** @constructor */
    initialize: function(a, b) {
        this.maxBufferRecords = parseInt(a) || 0;
        this.verbose = !!b || false;
    }
});
jscape.LogConfiguration.fromJSON = function(data) {
    return data ? new jscape.LogConfiguration(data.maxBufferRecords, data.verbose) : null;
};


/** @class */
jscape.domain.LoggingModule = jscape.domain.DomainModule.extend(
    /** @lends {jscape.domain.LoggingModule.prototype} */
{
    onCreate: function () {
        this._super.apply(this, arguments);

        this.eventLogController = new jscape.domain.EventLogController();
        this.eventLogController.onCreate(this.managementService, this.domainName);

        this.searchController = new jscape.domain.LogSearchController();
        this.searchController.onCreate(this.managementService, this.domainName);

        this.serviceController = new jscape.domain.LogServiceController();
        this.serviceController.onCreate(this.managementService, this.domainName);

        this.syslogController = new jscape.domain.SyslogController();
        this.syslogController.onCreate(this.managementService, this.domainName);

        this.configController = new jscape.domain.LogConfigController();
        this.configController.onCreate(this.managementService, this.domainName);
    },

    onStart: function () {
        this.eventLogController.onStart();
        this.searchController.onStart();
        this.serviceController.onStart();
        this.syslogController.onStart();
        this.configController.onStart();
    },

    onStop: function () {
        this.eventLogController.onStop();
    },

    onPause: function () {
        this.eventLogController.onPause();

        this._confirmAndApply($.grep([
                                         this.eventLogController,
                                         this.searchController,
                                         this.serviceController,
                                         this.syslogController,
                                         this.configController
                                     ],
                                     function (controller) {
                                         return controller.hasChanged();
                                     }));
    },

    onResume: function () {
        this.eventLogController.onResume();
        this.searchController.onResume();
        this.serviceController.onResume();
        this.syslogController.onResume();
        this.configController.onResume();
    }
});

/** @class */
jscape.domain.EventLogController = Class.extend(
    /** @lends {jscape.domain.EventLogController.prototype} */
{
    DELAY: 5 * 1000,

    view: null,
    timerId: null,
    buffer: null,

    onCreate: function (managementService, domainName) {
        this.managementService = managementService;
        this.domainName = domainName;

        this.buffer = new jscape.domain.LogBuffer();
    },

    onStart: function () {
        if (this.view == null) {
            this.view = new jscape.domain.EventLogView();
        }
        this.buffer.setLength(this.view.getMaxRecords());
        this.view.show(this);
    },

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

    onResume: function() {
        if (!this.view.isPaused()) {
            this._startPoll(0);
        }
    },

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

    hasChanged: function() {
        return false;
    },

    onMaxRecordsChanged: function(newValue, oldValue) {
        if (newValue < oldValue) {
            this.buffer.setLength(newValue);
            this._setupView();
        } else if (newValue > oldValue) {
            this.buffer.setLength(newValue);
        }
    },

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

    onResumeLog: function() {
        this._startPoll(0);
    },

    _poll: function (delay) {
        this._stopPoll();
        this.timerId = setTimeout($.proxy(function () {
            this.timerId = null;
            this.managementService.getLogs(this.domainName)
                    .done($.proxy(function (data) {
                              this.buffer.append(data || "");
                              this._setupView();
                              this._poll(this.DELAY);
                          }, this))
                    .fail($.proxy(this._stopPoll, this));
        }, this), delay || 0);
    },

    _startPoll: function(delay) {
        this._stopPoll();
        this._poll(arguments.length == 0 ? this.DELAY : delay);
    },

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

    _setupView: function() {
        this.view.setLogRecords(this.buffer.toString());
    }
});

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

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

    setLogRecords: function(value) {
        this.records.val(value);
    },

    isPaused: function() {
        return this.pauseButton.linkbutton("options").selected;
    },

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

    _onChange$MaxRecords: function(newValue, oldValue) {
        this.listener.onMaxRecordsChanged(parseInt(newValue), parseInt(oldValue));
    },

    _onClick$PauseButton: function() {
        this._adjustPauseButtonText();

        if (!this.isPaused()) {
            this.listener.onResumeLog();
        } else {
            this.listener.onPauseLog();
        }
    },

    _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.domain.EventLogView.LISTENER = {
    onMaxRecordsChanged: $.noop,
    onPauseLog: $.noop,
    onResumeLog: $.noop
};


/** @class */
jscape.domain.LogServiceController = Class.extend(
    /** @lends {jscape.domain.LogServiceController.prototype} */
{
    DEFAULT_DESCRIPTOR: jscape.LogService.file("", jscape.LogService.FILE_STRATEGY.DAILY, 10 * 1024),

    type: null,
    descriptor: null,
    view: null,

    /** @constructor */
    initialize: function () {
        this.controllers = {
            FILE: jscape.domain.FileLogServiceController,
            DB: jscape.domain.DbLogServiceController
        };
    },

    onCreate: function (managementService, domainName) {
        this.managementService = managementService;
        this.domainName = domainName;
    },

    onStart: function () {
        if (this.view == null) {
            this.view = new jscape.domain.LogServiceView();
        }
        this.view.show(this);
    },

    hasChanged: function() {
        var controller = this._currentController();
        var serviceType = (this.view.getType() || "").toUpperCase();
        return this.type != serviceType || (controller && controller.hasChanged());
    },

    onResume: function () {
        this.managementService.getLogService(this.domainName)
                .done($.proxy(function (descriptor) { this.descriptor = descriptor || this.DEFAULT_DESCRIPTOR; }, this))
                .fail($.proxy(function () { this.descriptor = this.DEFAULT_DESCRIPTOR; }, this))
                .always($.proxy(function () { this._setupView(this.descriptor); }, this));
    },

    onApply: function () {
        var controller = this._currentController();
        if (controller) {
            return controller.onApply()
                    .done($.proxy(function (descriptor) {
                              this.descriptor = descriptor;
                              this._fireApplySuccess();
                          }, this));
        } else {
            return $.Deferred().reject().promise();
        }
    },

    onDiscard: function () {
        var controller = this._currentController();
        if (controller) {
            controller.onDiscard();
        }
        this._setupView(this.descriptor);
    },

    onChangeType: function () {
        var serviceType = (this.view.getType() || "").toUpperCase();
        $.each(this.controllers, $.proxy(function (type, controller) {
            var t = $.type(controller);
            if (serviceType === type) {
                if (t === "function") {
                    this.controllers[type] = new controller();
                    this.controllers[type].start(this.managementService, this.domainName, this.descriptor);
                } else if (t === "object") {
                    controller.onResume();
                }
            } else {
                if (t === "object") {
                    controller.onPause();
                }
            }
        }, this));
    },

    _currentController: function() {
        var controller = this.controllers[(this.view.getType() || "").toUpperCase()];
        return $.type(controller) === "object" ? controller : null;
    },

    _setupView: function (descriptor) {
        this.type = jscape.LogService.typeOf(descriptor, jscape.LogService.Type.FILE);
        this.view.setType(this.type);
    },

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

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

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

        this.applyButton = $("a[role=button][name=apply]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ApplyButton, this)});
        this.discardButton = $("a[role=button][name=discard]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$DiscardButton, this)});
    },

    getType: function() {
        return this.type.combobox("getValue");
    },

    setType: function(value) {
        var select = this.type.combobox("getValue");
        this.type.combobox("setValue", value);
        if (select === value) {
            this._onChange$Type();
        }
    },

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

    _onChange$Type: function() {
        this.listener.onChangeType(this);
    },

    _onClick$ApplyButton: function() {
        this.applyButton.linkbutton("disable");
        this.listener.onApply(this)
                .always($.proxy(function () { this.applyButton.linkbutton("enable"); }, this));
    },

    _onClick$DiscardButton: function() {
        this.listener.onDiscard(this);
    }
});
jscape.domain.LogServiceView.LISTENER = {
    onChangeType: $.noop,
    onApply: $.noop,
    onDiscard: $.noop
};

/** @class */
jscape.domain.FileLogServiceController = Class.extend(
    /** @lends {jscape.domain.FileLogServiceController.prototype} */
{
    DEFAULT: {DIRECTORY: "%installdir%/logs/%domain%", STRATEGY: jscape.LogService.FILE_STRATEGY.DAILY},
    VARIABLES: ["installdir", "domain"],

    /** @constructor */
    initialize: function(container) {
        this.view = new jscape.domain.FileLogServiceView(container);
        this.variableController = new jscape.VariableController();
    },

    start: function(managementService, domainName, descriptor) {
        this.managementService = managementService;
        this.domainName = domainName;
        this.descriptor = descriptor;

        this._setupView(this.descriptor).show(this);
    },

    hasChanged: function() {
        return this.descriptor && !Object._equals(this.descriptor, this._createDescriptor());
    },

    onPause: function() {
        this.view.hide();
    },

    onResume: function() {
        this.view.show(this);
        this._setupView(this.descriptor);
    },

    onApply: function() {
        if (!this.view.valid()) {
            return $.Deferred().reject().promise();
        }
        var descriptor = this._createDescriptor();
        return this.managementService.setLogService(this.domainName, descriptor)
                .done($.proxy(function () { this.descriptor = descriptor; }, this));
    },

    onDiscard: function() {
        this._setupView(this.descriptor);
    },

    onAddVariable: function(input) {
        this.variableController.start(input, this.VARIABLES);
    },

    onSelectPath: function() {
        new SelectPathController($.proxy(this.managementService.listLogDir, this.managementService),
                                 $.proxy(this.managementService.createLogDir , this.managementService))
                .selectPath()
                .done($.proxy(function(entry) { this.view.setDirectory(entry.path); }, this));
    },

    _createDescriptor: function() {
        return jscape.LogService.file(this.view.getDirectory(),
                                      this.view.getStrategy(),
                                      this.view.getFileSize());
    },

    _setupView: function(descriptor) {
        if (jscape.LogService.Type.FILE == jscape.LogService.typeOf(descriptor, null)) {
            this.view.setDirectory(descriptor.directory);
            this.view.setStrategy(descriptor.strategyName);
            this.view.setFileSize(descriptor.fileSize);
        } else {
            this.view.setDirectory(this.DEFAULT.DIRECTORY);
            this.view.setStrategy(this.DEFAULT.STRATEGY);
        }
        return this.view;
    }
});

/** @class */
jscape.domain.FileLogServiceView = Class.extend(
    /** @lends {jscape.domain.FileLogServiceView.prototype} */
{
    /** @const */
    SIZE_FACTOR: 1024 * 1024,
    DEFAULT_SIZE: 10,

    /** @constructor */
    initialize: function(container) {
        this.fieldset = $("fieldset[name=filelogservicefields]", container).hide();

        this.directory = $("input[name=directory]", this.fieldset).textbox({required: true, validType: "length[1,500]", missingMessage: window.R.string.LOGGING_ERROR_BAD_DIR, invalidMessage: window.R.string.LOGGING_ERROR_BAD_DIR, tipPosition: "left", width: "50%"});
        this.directory.textbox("textbox").focus($.proxy(function() { this.addVariable.linkbutton("enable"); }, this));

        this.strategy = $("input[name=strategy]:radio", this.fieldset).change($.proxy(this._adjustFieldState, this));
        this.sizeStrategy = this.strategy.filter("[value=FileSize]");

        this.fileSize = $("input[name=filesize]", this.fieldset).numberspinner({required: true, min: 1, value: this.DEFAULT_SIZE, width: 80});

        this.browseButton = $("a[role=button][name=browsedir]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$BrowseButton, this)});
        this.addVariable = $("a[role=button][name=addvar]", this.fieldset).linkbutton({disabled: true, onClick: $.proxy(this._onClick$AddVariable, this)});
    },

    getDirectory: function() {
        return this.directory.textbox("getValue");
    },

    setDirectory: function(value) {
        this.directory.textbox("setValue", value);
    },

    getStrategy: function() {
        return this.strategy.filter(":checked").val();
    },

    setStrategy: function(value) {
        this.strategy.filter("[value=" + value + "]").prop("checked", true).change();
    },

    getFileSize: function() {
        return parseInt(this.fileSize.numberspinner("getValue")) * this.SIZE_FACTOR;
    },

    setFileSize: function(value) {
        this.fileSize.numberspinner("setValue", parseInt(value) / this.SIZE_FACTOR);
    },

    show: function(listener) {
        this.listener = listener || jscape.domain.FileLogServiceView.LISTENER;
        this.fieldset.show();
        this._adjustFieldState();
    },

    hide: function() {
        this.fieldset.hide();
    },

    valid: function() {
        return this.fieldset.form("validate");
    },

    _onClick$AddVariable: function() {
        this.addVariable.linkbutton("disable");
        this.listener.onAddVariable(this.directory.textbox("textbox"));
    },

    _onClick$BrowseButton: function() {
        this.listener.onSelectPath(this);
    },

    _adjustFieldState: function() {
        var enable = this.sizeStrategy.is(":checked");
        this.fileSize.numberspinner(enable ? "enable" : "disable").numberspinner(enable ? "enableValidation" : "disableValidation").numberspinner("validate");
    }
});
jscape.domain.FileLogServiceView.LISTENER = {
    onAddVariable: $.noop,
    onSelectPath: $.noop
};


/** @class */
jscape.domain.DbLogServiceController = Class.extend(
    /** @lends {jscape.domain.DbLogServiceController.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this.view = new jscape.domain.DbLogServiceView(container);
    },

    start: function(managementService, domainName, descriptor) {
        this.managementService = managementService;
        this.domainName = domainName;
        this.descriptor = descriptor;

        this._setupView(descriptor).show(this);
    },

    hasChanged: function() {
        return this.descriptor && !Object._equals(this.descriptor, this._createDescriptor());
    },

    onResume: function() {
        this.view.show(this);
        this._setupView(this.descriptor);
    },

    onPause: function() {
        this.view.hide();
    },

    onApply: function () {
        if (!this.view.valid()) {
            return $.Deferred().reject().promise();
        }
        var descriptor = this._createDescriptor();
        return this.managementService.setLogService(this.domainName, descriptor)
                .done($.proxy(function () { this.descriptor = descriptor; }, this));
    },

    onDiscard: function() {
        this._setupView(this.descriptor);
    },

    onTest: function() {
        var descriptor = this._createDescriptor();
        this.managementService.testLogService(this.domainName, descriptor)
                .done($.proxy(this._testPassed, this));
    },

    _createDescriptor: function() {
        return jscape.LogService.db(this.view.getUrl(),
                                    this.view.getUsername(),
                                    this.view.getPassword(),
                                    this.view.getPoolSize(),
                                    this.view.getPoolTimeout());
    },

    _setupView: function(descriptor) {
        if (jscape.LogService.Type.DB == jscape.LogService.typeOf(descriptor, null)) {
            this.view.setUrl(descriptor.url);
            this.view.setUsername(descriptor.username);
            this.view.setPassword(descriptor.password);
            this.view.setPoolSize(descriptor.poolSize);
            this.view.setPoolTimeout(descriptor.idleConnectionTTL);
        }
        return this.view;
    },

    _testPassed: function () {
        $.messager.alert(window.R.string.LOGGING_TEST_DB_TITLE,
                         window.R.string.LOGGING_TEST_DB_PASSED_MESSAGE,
                         "info");
    }
});

/** @class */
jscape.domain.DbLogServiceView = Class.extend(
    /** @lends {jscape.domain.DbLogServiceView.prototype} */
{
    /** @const */
    TIMEOUT_FACTOR: 60 * 1000,

    /** @constructor */
    initialize: function(container) {
        this.fieldset = $("fieldset[name=dblogservicefields]", container).hide();

        this.url = $("input[name=dburl]", this.fieldset).textbox({required: true, validType: "length[1,2048]", missingMessage: window.R.string.LOGGING_ERROR_BAD_DB_URL, invalidMessage: window.R.string.LOGGING_ERROR_BAD_DB_URL, width: 410});
        this.username = $("input[name=username]", this.fieldset).textbox({required: true, validType: "length[1,50]", missingMessage: window.R.string.LOGGING_ERROR_BAD_USER, invalidMessage: window.R.string.LOGGING_ERROR_BAD_USER, width: 250});
        this.password = $("input[name=password]", this.fieldset).textbox({type: "password", width: 250});
        this.poolSize = $("input[name=poolsize]", this.fieldset).numberspinner({min: 1, max: 100, value: 5, width: 50});
        this.poolTimeout = $("input[name=idlettl]", this.fieldset).numberspinner({min: 1, max: 100, value: 5, width: 50});

        this.testButton = $("a[role=button][name=testdb]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$TestButton, this)});
    },

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

    setUrl: function(value) {
        this.url.textbox("setValue", value);
    },

    getUsername: function() {
        return this.username.textbox("getValue");
    },

    setUsername: function(value) {
        this.username.textbox("setValue", value);
    },

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

    setPassword: function(value) {
        this.password.textbox("setValue", value);
    },

    getPoolSize: function() {
        return parseInt(this.poolSize.numberspinner("getValue"));
    },

    setPoolSize: function(value) {
        this.poolSize.numberspinner("setValue", parseInt(value));
    },

    getPoolTimeout: function() {
        return parseInt(this.poolTimeout.numberspinner("getValue")) * this.TIMEOUT_FACTOR;
    },

    setPoolTimeout: function(value) {
        this.poolTimeout.numberspinner("setValue", parseInt(value) / this.TIMEOUT_FACTOR);
    },

    show: function(listener) {
        this.listener = listener || jscape.domain.DbLogServiceView.LISTENER;
        this.fieldset.show().form("enableValidation").form("validate");
    },

    hide: function() {
        this.fieldset.hide().form("disableValidation");
    },

    valid: function() {
        return this.fieldset.form("validate");
    },

    _onClick$TestButton: function() {
        if (this.valid()) {
            this.listener.onTest(this);
        }
    }
});
jscape.domain.DbLogServiceView.LISTENER = {
    onTest: $.noop
};

/** @class */
jscape.domain.SyslogController = Class.extend(
    /** @lends {jscape.domain.SyslogController.prototype} */
{
    DEFAULT_DESCRIPTOR: new jscape.SyslogService("", 514, 1, "JSCAPE"),

    view: null,
    descriptor: null,

    onCreate: function (managementService, domainName) {
        this.managementService = managementService;
        this.domainName = domainName;
    },

    onStart: function () {
        if (this.view == null) {
            this.view = new jscape.domain.SyslogView();
        }
        this.view.show(this);
    },

    hasChanged: function() {
        return this.descriptor && !Object._equals(this.descriptor, this._createDescriptor());
    },

    onResume: function () {
        this.managementService.getSyslogService(this.domainName)
                .done($.proxy(function (descriptor) { this.descriptor = this._copyDescriptor(descriptor); }, this))
                .fail($.proxy(function () { this.descriptor = null; }, this))
                .always($.proxy(function () { this._setupView(this.descriptor); }, this));
    },

    onApply: function () {
        return this.managementService.setSyslogService(this.domainName, this._createDescriptor())
                .done($.proxy(function (descriptor) {
                          this.descriptor = this._copyDescriptor(descriptor);
                          this._fireApplySuccess();
                      }, this));
    },

    onDiscard: function () {
        var descriptor = this.descriptor;
        this.descriptor = this._copyDescriptor(descriptor);
        this._setupView(this.descriptor);
    },

    _createDescriptor: function () {
        if (this.view.isEnabled()) {
            return new jscape.SyslogService(this.view.getHost(),
                                            this.view.getPort(),
                                            this.view.getFacility(),
                                            this.view.getProcessName());
        }
        return null;
    },

    _copyDescriptor: function (descriptor) {
        return jscape.SyslogService.fromJSON(descriptor);
    },

    _setupView: function (descriptor) {
        this.view.setEnabled(descriptor != null);

        if (descriptor == null) {
            descriptor = this.DEFAULT_DESCRIPTOR;
        }
        this.view.setHost(descriptor.host);
        this.view.setPort(descriptor.port);
        this.view.setFacility(descriptor.facilityCode);
        this.view.setProcessName(descriptor.processName);
    },

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

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

        this.enabled = $("input[name=enabled]:checkbox", this.fieldset).change($.proxy(this._adjustFieldState, this));

        this.host = $("input[name=host]", this.fieldset).textbox({required: true, validType: "length[1,255]", missingMessage: window.R.string.LOGGING_ERROR_BAD_SYSLOG_HOST, invalidMessage: window.R.string.LOGGING_ERROR_BAD_SYSLOG_HOST, width: "40%"});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 0,  max: 65535, width: 100});
        this.facility = $("select[name=facility]", this.fieldset).combobox({required: true, editable: false, width: "25%"});
        this.process = $("input[name=processname]", this.fieldset).textbox({required: false, validType: "length[1,32]", invalidMessage: window.R.string.LOGGING_ERROR_BAD_SYSLOG_PROCESS_NAME, width: "40%"});

        this.applyButton = $("a[role=button][name=apply]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ApplyButton, this)});
        this.discardButton = $("a[role=button][name=discard]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$DiscardButton, this)});
    },

    isEnabled: function() {
        return this.enabled.is(":checked");
    },

    setEnabled: function(value) {
        this.enabled.prop("checked", !!value).change();
    },

    getHost: function() {
        return this.host.textbox("getValue");
    },

    setHost: function(value) {
        this.host.textbox("setValue", value);
    },

    getPort: function() {
        return parseInt(this.port.numberspinner("getValue"));
    },

    setPort: function(value) {
        this.port.numberspinner("setValue", parseInt(value));
    },

    getFacility: function() {
        return this.facility.combobox("getValue");
    },

    setFacility: function(value) {
        this.facility.combobox("setValue", value);
    },

    getProcessName: function() {
        return this.process.textbox("getValue");
    },

    setProcessName: function(value) {
        this.process.textbox("setValue", value);
    },

    show: function(listener) {
        this.listener = listener || jscape.domain.SyslogView.LISTENER;
        this._adjustFieldState();
    },

    _onClick$ApplyButton: function () {
        if (this.fieldset.form("validate")) {
            this.applyButton.linkbutton("disable");
            this.listener.onApply(this)
                    .always($.proxy(function () { this.applyButton.linkbutton("enable"); }, this));
        }
    },

    _onClick$DiscardButton: function() {
        this.listener.onDiscard(this);
    },

    _adjustFieldState: function() {
        var enable = this.isEnabled();
        this.host.textbox(enable ? "enable" : "disable").textbox(enable ? "enableValidation" : "disableValidation");
        this.port.numberspinner(enable ? "enable" : "disable").numberspinner(enable ? "enableValidation" : "disableValidation");
        this.facility.combobox(enable ? "enable" : "disable");
        this.process.textbox(enable ? "enable" : "disable");
        this.fieldset.form("validate");
    }
});
jscape.domain.SyslogView.LISTENER = {
    onApply: $.noop,
    onDiscard: $.noop
};

/** @class */
jscape.domain.LogConfigController = Class.extend(
    /** @lends {jscape.domain.LogConfigController.prototype} */
{
    DEFAULT_CONFIG: new jscape.LogConfiguration(100, false),

    config: null,
    view: null,

    onCreate: function (managementService, domainName) {
        this.managementService = managementService;
        this.domainName = domainName;
    },

    onStart: function () {
        if (this.view == null) {
            this.view = new jscape.domain.LogConfigView();
        }
        this.view.show(this);
    },

    hasChanged: function() {
        return this.config && !Object._equals(this.config, this._createConfiguration());
    },

    onResume: function () {
        return this.managementService.getLogConfiguration(this.domainName)
                .done($.proxy(function (config) { this.config = config || this._copyConfiguration(this.DEFAULT_CONFIG); }, this))
                .fail($.proxy(function () { this.config = this._copyConfiguration(this.DEFAULT_CONFIG); }, this))
                .always($.proxy(function () { this._setupView(this.config); }, this));
    },

    onApply: function () {
        return this.managementService.setLogConfiguration(this.domainName, this._createConfiguration())
                .done($.proxy(function (config) {
                          this.config = this._copyConfiguration(config);
                          this._fireApplySuccess();
                      }, this));
    },

    onDiscard: function() {
        var config = this.config;
        this.config = this._copyConfiguration(config);
        this._setupView(this.config);
    },

    _createConfiguration: function() {
        return new jscape.LogConfiguration(this.view.getMaxRecords(), this.view.getVerboseLog());
    },

    _copyConfiguration: function(config) {
        return jscape.LogConfiguration.fromJSON(config);
    },

    _setupView: function(config) {
        if (config && this.view) {
            this.view.setMaxRecords(config.maxBufferRecords);
            this.view.setVerboseLog(config.verbose);
        }
    },

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

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

        this.maxRecords = $("input[name=buffersize]", this.fieldset).numberspinner({required: true, min: 10, max: 1000, increment: 10, width: 100});
        this.verbose = $("input[name=verbose]:checkbox", this.fieldset);

        this.applyButton = $("a[role=button][name=apply]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$ApplyButton, this)});
        this.discardButton = $("a[role=button][name=discard]", this.fieldset).linkbutton({onClick: $.proxy(this._onClick$DiscardButton, this)});
    },

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

    setMaxRecords: function(value) {
        this.maxRecords.numberspinner("setValue", parseInt(value)).numberspinner("validate");
    },

    getVerboseLog: function() {
        return this.verbose.is(":checked");
    },

    setVerboseLog: function(value) {
        this.verbose.prop("checked", !!value);
    },

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

    _onClick$ApplyButton: function() {
        if (this.fieldset.form("validate")) {
            this.applyButton.linkbutton("disable");
            this.listener.onApply(this)
                    .always($.proxy(function() { this.applyButton.linkbutton("enable"); }, this));
        }
    },

    _onClick$DiscardButton: function() {
        this.listener.onDiscard(this);
    }
});
jscape.domain.LogConfigView.LISTENER = {
    onApply: $.noop,
    onDiscard: $.noop
};