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

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

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

    onPageSelected: function(page) {
    },

    onSubmit: function(dialog) {
        try {
            var descriptor = this._createDescriptor();
            this.managementService.storeDomain(descriptor)
                    .done($.proxy(function() {
                        dialog.hide();
                        this.managementService.startDomain(descriptor.name)
                                .always($.proxy(function() { this.deferred.resolve(descriptor.name); }, this));
                    }, this))
                    .fail($.proxy(function() { this.deferred.reject(); }, this));
        } catch (e) {
            this.deferred.reject();
        }
    },

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

    _setupDialog: function () {
        var dialog = new jscape.domain.AddDomainDialog();

        this.nameController = new jscape.domain.wizard.DomainNameController(dialog.container());
        dialog.addItem(this.nameController);

        this.serviceController = new jscape.domain.wizard.TransportServiceController(dialog.container());
        dialog.addItem(this.serviceController);

        this.logServiceController = new jscape.domain.wizard.LogServiceController(dialog.container());
        dialog.addItem(this.logServiceController);

        this.nameController.start(this.managementService);
        this.serviceController.start(this.managementService);
        this.logServiceController.start(this.managementService);

        return dialog;
    },

    _createDescriptor: function() {
        var transportService = this.serviceController.applyChanges();
        var loggingService = this.logServiceController.applyChanges();
        return new jscape.DomainDescriptor(this.nameController.getDomainName(),
                                           this.nameController.getDomainDescription(),
                                           [transportService, loggingService]);
    }
});

/** @class */
jscape.domain.AddDomainDialog = jscape.view.WizardDialog.extend(
    /** @lends {jscape.domain.AddDomainDialog.prototype} */
{
    /** @constructor */
    initialize: function() {
        this._super($("#add-domain-wizard"));
    }
});

/** @class */
jscape.domain.wizard.BaseDomainServiceController = Class.extend(
    /** @lends {jscape.domain.wizard.BaseDomainServiceController.prototype} */
{
    view: null,

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

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

    valid: function () {
        return this.view.valid();
    },

    applyChanges: function () {
        return this.view.valid() ? this._createDescriptor() : null;
    },

    _createDescriptor: function() {
        throw "Abstract method.";
    }
});

/** @class */
jscape.domain.wizard.BaseDomainServiceView = Class.extend(
    /** @lends {jscape.domain.wizard.BaseDomainServiceView.prototype} */
{
    fieldset: null,

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

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

    show: function() {
        this.fieldset.show().form("validate");
        this.fieldset.find(":input:visible:not(:disabled)").first().focus();
    },

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

/** @class */
jscape.domain.wizard.DomainNameController = jscape.view.WizardDialog.Page.extend(
    /** @lends {jscape.domain.wizard.DomainNameController.prototype} */
{
    domainNames: null,

    /** @constructor */
    initialize: function(container) {
        this.view = new jscape.domain.wizard.DomainNameView(container);

        this._initValidators();
    },

    /** @override */
    start: function(managementService) {
        managementService.getDomainNames()
                .done($.proxy(function(names) { this.domainNames = names || []; }, this))
                .fail($.proxy(function() { this.domainNames = []; }, this));
    },

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

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

    valid: function() {
        return this.view.valid();
    },

    getDomainName: function() {
        return this.view.getName();
    },

    getDomainDescription: function() {
        return this.view.getDescription();
    },

    _initValidators: function() {
        var v = new jscape.Validator();
        v.rule("domain_name", $.proxy(this._domainNameValid, this), window.R.string.DOMAIN_ERROR_BAD_NAME);
        v.rule("domain_unique", $.proxy(this._domainNotExists, this), window.R.string.DOMAIN_ERROR_NAME_EXISTS);
        v.rule("domain_description", $.proxy(this._domainDescriptionValid, this), window.R.string.DOMAIN_ERROR_BAD_DESCRIPTION);
    },

    _domainNotExists: function(value) {
        return $.inArray(value, this.domainNames) == -1;
    },

    _domainNameValid: function(value) {
        return value && value.trim().length != 0 && value.charAt(value.length - 1) != ' ' && !/[<>\\/]/g.test(value);
    },

    _domainDescriptionValid: function(value) {
        return typeof value !== "string" || value.length < 1024;
    }
});

/** @class */
jscape.domain.wizard.DomainNameView = Class.extend(
    /** @lends {jscape.domain.wizard.DomainNameView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this.fieldset = $("fieldset[name=domainparametersfields]", container).hide();

        this.name = $("input[name=name]", this.fieldset).textbox({required: true, validType: ["domain_name", "domain_unique"], missingMessage: window.R.string.DOMAIN_ERROR_BAD_NAME, width: "65%"});
        this.description = $("textarea[name=description]", this.fieldset).textbox({required: false, multiline: true, validType: "domain_description", width: "65%", height: 150});
    },

    getName: function() {
        return this.name.textbox("getValue");
    },

    getDescription: function() {
        return this.description.textbox("getValue");
    },

    show: function() {
        this.fieldset.show();
        this.name.textbox("textbox").focus();
    },

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

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

/** @class */
jscape.domain.wizard.TransportServiceController = jscape.view.ListView.extend(
    /** @lends {jscape.domain.wizard.TransportServiceController.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super();
        this.view = new jscape.domain.wizard.TransportServiceView(container);

        this.addItem(jscape.Service.Protocol.AFTP, jscape.domain.wizard.AftpServiceController);
        this.addItem(jscape.Service.Protocol.AS2, jscape.domain.wizard.As2ServiceController);
        this.addItem(jscape.Service.Protocol.FTP, jscape.domain.wizard.FtpServiceController);
        this.addItem(jscape.Service.Protocol.HTTP, jscape.domain.wizard.HttpServiceController);
        this.addItem(jscape.Service.Protocol.OFTP, jscape.domain.wizard.OftpServiceController);
        this.addItem(jscape.Service.Protocol.SFTP, jscape.domain.wizard.SftpServiceController);
        this.addItem(jscape.Service.Protocol.WEBDAV, jscape.domain.wizard.WebDavServiceController);
    },

    start: function(managementService) {
        this.managementService = managementService;

        this.view.show(this);

        this._loadData()
                .always($.proxy(function() {
                    this.view.setProtocol(jscape.Service.Protocol.FTP);
                }, this));
    },

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

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

    valid: function() {
        var item = this.getItem(this.getCurrentItem());
        return $.type(item) === "object" ? item.valid() : true;
    },

    applyChanges: function() {
        var item = this.getItem(this.getCurrentItem());
        return $.type(item) === "object" ? item._createDescriptor() : null;
    },

    onChangeProtocol: function () {
        this.setCurrentItem(this.view.getProtocol().toUpperCase());
    },

    _loadData: function () {
        return $.when(this.managementService.getServerKeys(), this.managementService.getServerAddresses())
                .done($.proxy(function (serverKeys, addresses) {
                    this.privateKeys = $.map(serverKeys, function (key) { return key.name; });
                    this.hosts = addresses;
                }, this));
    },

    /** @override */
    _createItem: function(item) {
        var controller = new item(this.view.container());
        controller.start(this.hosts, this.privateKeys);
        return controller;
    }
});

/** @class */
jscape.domain.wizard.TransportServiceView = Class.extend(
    /** @lends {jscape.domain.wizard.TransportServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this.fieldset = $("fieldset[name=domainservicefields]", container).hide();

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

    getProtocol: function() {
        return this.protocol.combobox("getValue");
    },

    setProtocol: function (value) {
        var select = this.protocol.combobox("getValue");
        this.protocol.combobox("setValue", value);
        if (select === value) {
            this._onChange$Protocol();
        }
    },

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

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

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

    _onChange$Protocol: function() {
        this.listener.onChangeProtocol(this);
    }
});
jscape.domain.wizard.TransportServiceView.LISTENER = {
    onChangeProtocol: $.noop
};

/** @class */
jscape.domain.wizard.FtpServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.FtpServiceController.prototype} */
{
    DEFAULTS: {
        "regular": {port: 21, keyUsed: false},
        "explicit SSL": {port: 21, keyUsed: true},
        "forced explicit SSL": {port: 21, keyUsed: true},
        "implicit SSL": {port: 990, keyUsed: true}
    },

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

    start: function(hosts, keys) {
        this.view.setHosts(hosts);
        this.view.setKeys(keys);
        this.view.show(this);

        this.view.setType(jscape.Service.FTP_TYPE.EXPLICIT_SSL);
    },

    onChangeType: function () {
        var type = this.view.getType();
        if (this.DEFAULTS.hasOwnProperty(type)) {
            this.view.setPort(this.DEFAULTS[type].port);
            this.view.setKeyUsed(this.DEFAULTS[type].keyUsed);
        }
    },

    _createDescriptor: function () {
        return jscape.Service.ftp(this.view.getHost(),
                                  this.view.getPort(),
                                  this.view.getType(),
                                  this.view.getKeyAlias());
    }
});

/** @class */
jscape.domain.wizard.FtpServiceView = jscape.domain.wizard.BaseDomainServiceView.extend(
    /** @lends {jscape.domain.wizard.FtpServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=ftpservicefields]", container));

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.DOMAIN_ERROR_BAD_HOST, invalidMessage: window.R.string.DOMAIN_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.type = $("select[name=type]", this.fieldset).combobox({required: true, editable: false, onChange: $.proxy(this._onChange$Type, this), width: 170, panelHeight: "auto"});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170, panelHeight: "auto"});
    },

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

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

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

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

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

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

    setKeyUsed: function(value) {
        this.keyAlias.combobox(!!value ? "enable" : "disable").combobox(!!value ? "enableValidation" : "disableValidation");
    },

    /** @override */
    show: function(listener) {
        this.listener = listener || jscape.domain.wizard.FtpServiceView.LISTENER;
        this._super();
    },

    _onChange$Type: function() {
        if (this.listener) {
            this.listener.onChangeType(this);
        }
    }
});
jscape.domain.wizard.FtpServiceView.LISTENER = {
    onChangeType: $.noop
};

/** @class */
jscape.domain.wizard.OftpServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.OftpServiceController.prototype} */
{
    DEFAULT_PORT: 3305,

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

    start: function(hosts, keys) {
        this.view.setHosts(hosts);
        this.view.setKeys(keys);
        this.view.setPort(this.DEFAULT_PORT);
        this.view.setUseSsl(true);
        this.view.setFileEncryptionRequired(true);
        this.view.setFileSignatureRequired(true);
        this.view.show();
    },

    _createDescriptor: function () {
        return jscape.Service.oftp(this.view.getHost(),
                                   this.view.getPort(),
                                   this.view.getIdCode(),
                                   this.view.getKeyAlias(),
                                   this.view.isUseSsl(),
                                   this.view.isFileEncryptionRequired(),
                                   this.view.isFileSignatureRequired());
    }
});

/** @class */
jscape.domain.wizard.OftpServiceView = jscape.domain.wizard.BaseDomainServiceView.extend(
    /** @lends {jscape.domain.wizard.OftpServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=oftpservicefields]", container));

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.DOMAIN_ERROR_BAD_HOST, invalidMessage: window.R.string.DOMAIN_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.idCode = $("input[name=idcode]", this.fieldset).textbox({required: true, validType: "length[1,500]", missingMessage: window.R.string.DOMAIN_ERROR_BAD_ID_CODE, invalidMessage: window.R.string.DOMAIN_ERROR_BAD_ID_CODE, width: 310});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto"});

        this.useSsl = $("input[name=usessl]:checkbox", this.fieldset);
        this.fileEncryption = $("input[name=fileencryption]:checkbox", this.fieldset);
        this.fileSignature = $("input[name=filesignature]:checkbox", this.fieldset);
    },

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

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

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

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

    getIdCode: function() {
        return this.idCode.textbox("getValue");
    },

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

    isUseSsl: function() {
        return this.useSsl.is(":checked");
    },

    setUseSsl: function(value) {
        this.useSsl.prop("checked", !!value);
    },

    isFileEncryptionRequired: function() {
        return this.fileEncryption.is(":checked");
    },

    setFileEncryptionRequired: function(value) {
        this.fileEncryption.prop("checked", !!value);
    },

    isFileSignatureRequired: function() {
        return this.fileSignature.is(":checked");
    },

    setFileSignatureRequired: function(value) {
        this.fileSignature.prop("checked", !!value);
    }
});

/** @class */
jscape.domain.wizard.SftpServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.SftpServiceController.prototype} */
{
    DEFAULT_PORT: 22,

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

    start: function(hosts, keys) {
        this.view.setPort(this.DEFAULT_PORT);
        this.view.setHosts(hosts);
        this.view.setKeys(keys);
        this.view.show();
    },

    _createDescriptor: function () {
        return jscape.Service.sftp(this.view.getHost(),
                                   this.view.getPort(),
                                   this.view.getAuthentication(),
                                   this.view.getKeyAlias());
    }
});

/** @class */
jscape.domain.wizard.SftpServiceView = jscape.domain.wizard.BaseDomainServiceView.extend(
    /** @lends {jscape.domain.wizard.SftpServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=sftpservicefields]", container));

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.DOMAIN_ERROR_BAD_HOST, invalidMessage: window.R.string.DOMAIN_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto"});
        this.auth = $("select[name=auth]", this.fieldset).combobox({required: true, editable: false, width: 170, panelHeight: "auto"});
    },

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

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

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

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

    getAuthentication: function() {
        return this.auth.combobox("getValue");
    },

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    }
});

/** @class */
jscape.domain.wizard.AftpServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.AftpServiceController.prototype} */
{
    DEFAULT_PORT: 3000,

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

    start: function(hosts, keys) {
        this.view.setPort(this.DEFAULT_PORT);
        this.view.setHosts(hosts);
        this.view.setKeys(keys);
        this.view.show();
    },

    _createDescriptor: function () {
        return jscape.Service.aftp(this.view.getHost(),
                                   this.view.getPort(),
                                   this.view.getKeyAlias(),
                                   this.view.isProtectionRequired());
    }
});

/** @class */
jscape.domain.wizard.AftpServiceView = jscape.domain.wizard.BaseDomainServiceView.extend(
    /** @lends {jscape.domain.wizard.AftpServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=aftpservicefields]", container));

        this.host = $("select[name=host]", this.fieldset).combobox({required: true, width: 200,  panelHeight: "auto", validType: "length[1,500]", missingMessage: window.R.string.DOMAIN_ERROR_BAD_HOST, invalidMessage: window.R.string.DOMAIN_ERROR_BAD_HOST});
        this.port = $("input[name=port]", this.fieldset).numberspinner({required: true, min: 1, max: 65535, width: 80});
        this.keyAlias = $("select[name=privatekey]", this.fieldset).combobox({required: true, editable: false, width: 170,  panelHeight: "auto"});
        this.protectionRequired = $("input[name=requiresecure]:checkbox", this.fieldset);
    },

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

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

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

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

    getKeyAlias: function() {
        return !this.keyAlias.combobox("options").disabled ? this.keyAlias.combobox("getValue") : null;
    },

    setKeys: function(values) {
        this.keyAlias.combobox("loadData", values);
    },

    isProtectionRequired: function() {
        return this.protectionRequired.is(":checked");
    }
});

/** @class */
jscape.domain.wizard.HttpServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.HttpServiceController.prototype} */
{
    /** @constructor */
    initialize: function (container) {
        this.view = new jscape.domain.wizard.HttpServiceView(container);
    },

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

    _createDescriptor: function () {
        return jscape.Service.http(this.view.isPlain(), this.view.isSecure());
    }
});

/** @class */
jscape.domain.wizard.BaseWebServiceView = jscape.domain.wizard.BaseDomainServiceView.extend(
    /** @lends {jscape.domain.wizard.BaseWebServiceView.prototype} */
{
    /** @constructor */
    initialize: function(fieldset) {
        this._super(fieldset);

        this.plain = $("input[name=plain]:checkbox", fieldset);
        this.secure = $("input[name=secure]:checkbox", fieldset);
    },

    isPlain: function() {
        return this.plain.is(":checked");
    },

    setPlain: function(value) {
        this.plain.prop("checked", !!value);
    },

    isSecure: function() {
        return this.secure.is(":checked");
    },

    setSecure: function(value) {
        this.secure.prop("checked", !!value);
    }
});

/** @class */
jscape.domain.wizard.HttpServiceView = jscape.domain.wizard.BaseWebServiceView.extend(
    /** @lends {jscape.domain.wizard.HttpServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=httpservicefields]", container));
    }
});

/** @class */
jscape.domain.wizard.WebDavServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.WebDavServiceController.prototype} */
{
    /** @constructor */
    initialize: function (container) {
        this.view = new jscape.domain.wizard.WebDavServiceView(container);
    },

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

    _createDescriptor: function () {
        return jscape.Service.webdav(this.view.isPlain(), this.view.isSecure());
    }
});

/** @class */
jscape.domain.wizard.WebDavServiceView = jscape.domain.wizard.BaseWebServiceView.extend(
    /** @lends {jscape.domain.wizard.WebDavServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=webdavservicefields]", container));
    }
});

/** @class */
jscape.domain.wizard.As2ServiceController = jscape.domain.wizard.BaseDomainServiceController.extend(
    /** @lends {jscape.domain.wizard.As2ServiceController.prototype} */
{
    /** @constructor */
    initialize: function (container) {
        this.view = new jscape.domain.wizard.As2ServiceView(container);
    },

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

    _createDescriptor: function () {
        return jscape.Service.as2(this.view.isPlain(), this.view.isSecure());
    }
});

/** @class */
jscape.domain.wizard.As2ServiceView = jscape.domain.wizard.BaseWebServiceView.extend(
    /** @lends {jscape.domain.wizard.As2ServiceView.prototype} */
{
    /** @constructor */
    initialize: function(container) {
        this._super($("fieldset[name=as2servicefields]", container));
    }
});

/** @class */
jscape.domain.wizard.LogServiceController = jscape.view.ListView.extend(
    /** @lends {jscape.domain.wizard.LogServiceController.prototype} */
{
    /** @constructor */
    initialize: function (container) {
        this._super();
        this.view = new jscape.domain.wizard.LogServiceView(container);

        this.addItem(jscape.LogService.Type.FILE, jscape.domain.wizard.FileLogServiceController);
        this.addItem(jscape.LogService.Type.DB, jscape.domain.wizard.DbLogServiceController);
    },

    start: function (managementService) {
        this.managementService = managementService;
        this.view.show(this);
        this.view.setType(jscape.LogService.Type.FILE);
    },

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

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

    valid: function() {
        var item = this.getItem(this.getCurrentItem());
        return $.type(item) === "object" ? item.valid() : true;
    },

    applyChanges: function() {
        var item = this.getItem(this.getCurrentItem());
        return $.type(item) === "object" ? item.applyChanges() : null;
    },

    onChangeType: function () {
        this.setCurrentItem(this.view.getType().toUpperCase());
    },

    /** @override */
    _createItem: function(item) {
        var controller = new item(this.view.container());
        controller.start(this.managementService);
        return controller;
    }
});

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

        this.type = $("select[name=type]", this.fieldset).combobox({required: true, editable: false, width: 120, panelHeight: "auto", onChange: $.proxy(this._onChange$Type, 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();
        }
    },

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

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

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

    _onChange$Type: function() {
        this.listener.onChangeType(this);
    }
});
jscape.domain.wizard.LogServiceView.LISTENER = {
    onChangeType: $.noop
};

/** @class */
jscape.domain.wizard.FileLogServiceController = Class.extend(
    /** @lends {jscape.domain.wizard.FileLogServiceController.prototype} */
{
    DEFAULT_DESCRIPTOR: jscape.LogService.file("%installdir%/logs/%domain%", jscape.LogService.FILE_STRATEGY.DAILY, 10 * 1024 * 1024),
    VARIABLES: ["installdir", "domain"],

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

    start: function(managementService) {
        this.managementService = managementService;

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

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

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

    valid: function() {
        return this.view.valid();
    },

    applyChanges: function() {
        return this.view.valid() ? this._createDescriptor() : null;
    },

    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);
        }
        return this.view;
    }
});

/** @class */
jscape.domain.wizard.FileLogServiceView = Class.extend(
    /** @lends {jscape.domain.wizard.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.wizard.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.wizard.FileLogServiceView.LISTENER = {
    onAddVariable: $.noop,
    onSelectPath: $.noop
};

/** @class */
jscape.domain.wizard.DbLogServiceController = Class.extend(
    /** @lends {jscape.domain.wizard.DbLogServiceController.prototype} */
{
    DEFAULT_DESCRIPTOR: jscape.LogService.db("jdbc:", "", null, 5, 5 * 60 * 1000),

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

    start: function(managementService) {
        this.managementService = managementService;

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

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

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

    valid: function() {
        return this.view.valid();
    },

    applyChanges: function () {
        return this.view.valid() ? this._createDescriptor() : null;
    },

    onTest: function() {
        var descriptor = this._createDescriptor();
        this.managementService.testLogService(null, 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.wizard.DbLogServiceView = Class.extend(
    /** @lends {jscape.domain.wizard.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.wizard.DbLogServiceView.LISTENER;
        this.fieldset.show().form("enableValidation").form("validate");
        this.url.textbox("textbox").select().focus();
    },

    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.wizard.DbLogServiceView.LISTENER = {
    onTest: $.noop
};
