jscape.settings = jscape.settings || {};

/** @class */
jscape.JmxServiceConfiguration = Class.extend(
    /** @lends {jscape.JmxServiceConfiguration.prototype} */
{
    /** @constructor */
    initialize: function(a, b, c, d) {
        this.enabled = a || false;
        this.host = b || "";
        this.port = parseInt(c) || 0;
        this.serverPort = parseInt(d) || null;
    }
});
jscape.JmxServiceConfiguration.fromJSON = function(data) {
    return data ? new jscape.JmxServiceConfiguration(data.enabled, data.host, data.port, data.serverPort) : null;
};

/** @class */
jscape.settings.JmxModule = jscape.settings.SettingsModule.extend(
    /** @lends {jscape.settings.JmxModule.prototype} */
{
    onCreate: function(managementService, serverAddresses) {
        this._super.apply(this, arguments);

        this.controller = new jscape.settings.JmxController();
        this.controller.onCreate(managementService, serverAddresses);
    },

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

    onPause: function () {
        if (this.controller.hasChanged()) {
            this._confirmAndApply([this.controller]);
        }
    },

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

/** @class */
jscape.settings.JmxController = Class.extend(
    /** @lends {jscape.settings.JmxController.prototype} */
{
    /** @const */
    DEFAULT_CONFIG: new jscape.JmxServiceConfiguration(false, "0.0.0.0", 30050, 30051),
    URL_TEMPLATE: "service:jmx:rmi://{host}:{serverPort}/jndi/rmi://{host}:{registryPort}/server",

    config: null,
    view: null,

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

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

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

    onResume: function () {
        this.managementService.getJmxServiceConfiguration()
                .done($.proxy(function (config) { this.config = config; }, this))
                .fail($.proxy(function () { this.config = this.DEFAULT_CONFIG; }, this))
                .always($.proxy(function () { this.view && this._setupView(this.config); }, this))
    },

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

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

    onDiscard: function() {
        this._setupView(this.config);
        return $.Deferred().resolve().promise();
    },

    onChange: function() {
        this.view.setUrl(this._createJmxUrl());
    },

    _createConfiguration: function() {
        return new jscape.JmxServiceConfiguration(this.view.getEnabled(),
                                                  this.view.getHost(),
                                                  this.view.getRegistryPort(),
                                                  this.view.getServerPort());
    },

    _createJmxUrl: function() {
        var config = this._createConfiguration();
        return this.URL_TEMPLATE.supplant({
            host: config.host,
            serverPort: config.serverPort != null ? config.serverPort : config.port + 1,
            registryPort: config.port
        });
    },

    _setupView: function(config) {
        this.view.setHosts(this.inetAddresses);

        if (config) {
            this.view.setHost(config.host);
            this.view.setRegistryPort(config.port);
            this.view.setServerPort(config.serverPort != null ? config.serverPort : config.port);
            this.view.setEnabled(config.enabled);
        }
    },

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

    _notSamePort: function() {
        return this.view.getServerPort() != this.view.getRegistryPort();
    },

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

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

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

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, editable: false, disabled: true, onChange: $.proxy(this._onForm$Change, this), missingMessage: window.R.string.JMX_ERROR_BAD_HOST, width: 170, panelWidth: 255, panelHeight: "auto"});
        this.serverPort = $("input[name=serverport]", this.fieldset).numberspinner({required: true, disabled: true, validType: "jmx_ports", min: 1, max: 65535, onChange: $.proxy(this._onForm$Change, this), width: 100});
        this.registryPort = $("input[name=registryport]", this.fieldset).numberspinner({required: true, disabled: true, validType: "jmx_ports", min: 1, max: 65535, onChange: $.proxy(this._onForm$Change, this), width: 100});
        this.jmxUrl = $("#jmx-service-url", 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({disabled: true, onClick: $.proxy(this._onClick$DiscardButton, this)});
    },

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

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

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

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

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

    setHosts: function(values) {
        this.host.combobox("loadData", values);
    },

    getServerPort: function() {
        return parseInt(this.serverPort.numberspinner("getValue"));
    },

    setServerPort: function(value) {
        this.serverPort.numberspinner("setValue", value);
    },

    getRegistryPort: function() {
        return parseInt(this.registryPort.numberspinner("getValue"));
    },

    setRegistryPort: function(value) {
        this.registryPort.numberspinner("setValue", value);
    },

    setUrl: function(url) {
        this.jmxUrl.text(url);
    },

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

    _onClick$DiscardButton: function() {
        this.listener.onDiscard();
        this.discardButton.linkbutton("disable");
    },

    _onForm$Change: function() {
        this._adjustFieldState();
        this.listener.onChange(this);
        this.discardButton.linkbutton("enable");
    },

    _adjustFieldState: function() {
        var enabled = this.enabled.is(":checked");
        this.host.combobox(enabled ? "enable" : "disable").combobox(enabled ? "enableValidation" : "disableValidation");
        this.serverPort.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        this.registryPort.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        this.jmxUrl.css("color", enabled ? "" : "#999");

        this.fieldset.form("validate");
    }
});
jscape.settings.JmxView.LISTENER = {
    onChange: $.noop,
    onApply: $.noop,
    onDiscard: $.noop
};