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

/** @class */
jscape.PasswordCompliance = Class.extend(
    /** @lends {jscape.PasswordCompliance.prototype} */
{
    /** @constructor */
    initialize: function (a, b, c, d, e, f, g, h, i, j, k, l) {
        this.minPasswordLength = parseInt(a) || null;
        this.minPasswordAge = parseInt(b) || null;
        this.maxPasswordAge = parseInt(c) || null;
        this.passwordExpirationNotificationDays = parseInt(d) || null;
        this.equalPasswordsHistoryLength = parseInt(e) || null;
        this.uppercaseRequired = f || false;
        this.lowercaseRequired = g || false;
        this.numericRequired = h || false;
        this.nonAlphaNumericRequired = i || false;
        this.nonCompliantPasswordLoginDenied = j || false;
        this.firstTimeLoginResetPasswordRequired = k || false;
        this.usernamePattern = l || null;
    }
});
jscape.PasswordCompliance.fromJSON = function(data) {
    return data ? new jscape.PasswordCompliance(data.minPasswordLength, data.minPasswordAge, data.maxPasswordAge, data.passwordExpirationNotificationDays, data.equalPasswordsHistoryLength, data.uppercaseRequired, data.lowercaseRequired, data.numericRequired, data.nonAlphaNumericRequired, data.nonCompliantPasswordLoginDenied, data.firstTimeLoginResetPasswordRequired, data.usernamePattern) : new jscape.PasswordCompliance();
};

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

        this.controller = new jscape.domain.ComplianceController();
        this.controller.onCreate(this.managementService, this.domainName);
    },

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

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

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

/** @class */
jscape.domain.ComplianceController = Class.extend(
    /** @lends {jscape.domain.ComplianceController.prototype} */
{
    DEFAULT_DESCRIPTOR: new jscape.PasswordCompliance(),

    view: null,
    descriptor: null,

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

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

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

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

        this.managementService.getFipsModeState(this.domainName)
                .done($.proxy(function (required) { this.view.setFipsModeState(required); }, this));
    },

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

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

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

    onChangeFipsMode: function(checked) {
        return this.managementService.setFipsModeState(this.domainName, checked)
                .done($.proxy(this._fireApplySuccess, this))
                .done($.proxy(function () { $(document).triggerHandler("domainstatechange"); }, this));
    },

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

    _createDescriptor: function () {
        return new jscape.PasswordCompliance(this.view.getMinPasswordLength(),
                                             this.view.getMinPasswordAge(),
                                             this.view.getMaxPasswordAge(),
                                             this.view.getPasswordExpirationNotificationDays(),
                                             this.view.getEqualPasswordsHistoryLength(),
                                             this.view.getUppercaseRequired(),
                                             this.view.getLowercaseRequired(),
                                             this.view.getNumericRequired(),
                                             this.view.getNonAlphaNumericRequired(),
                                             this.view.getNonCompliantPasswordDenied(),
                                             this.view.getFirstTimeLoginResetPasswordRequired(),
                                             this.view.getUsernamePattern());
    },

    _setupView: function (descriptor) {
        if (descriptor && this.view) {
            this.view.setMinPasswordLength(descriptor.minPasswordLength);
            this.view.setMinPasswordAge(descriptor.minPasswordAge);
            this.view.setMaxPasswordAge(descriptor.maxPasswordAge);
            this.view.setPasswordExpirationNotificationDays(descriptor.passwordExpirationNotificationDays);
            this.view.setEqualPasswordsHistoryLength(descriptor.equalPasswordsHistoryLength);
            this.view.setUppercaseRequired(descriptor.uppercaseRequired);
            this.view.setLowercaseRequired(descriptor.lowercaseRequired);
            this.view.setNumericRequired(descriptor.numericRequired);
            this.view.setNonAlphaNumericRequired(descriptor.nonAlphaNumericRequired);
            this.view.setNonCompliantPasswordDenied(descriptor.nonCompliantPasswordLoginDenied);
            this.view.setFirstTimeLoginResetPasswordRequired(descriptor.firstTimeLoginResetPasswordRequired);
            this.view.setUsernamePattern(descriptor.usernamePattern);
        }
    },

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

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

    _patternValid: function(value) {
        var result = this.managementService.testUsernameCompliancePattern(this.domainName, value);
        if ($.isPlainObject(result)) {
            if (result.valid === false && result.message) {
                new jscape.Validator().ruleMessage("username_pattern", result.message);
            }
            return !!result.valid;
        }
        return true;
    }
});

/** @class */
jscape.domain.ComplianceView = Class.extend(
    /** @lends {jscape.domain.ComplianceView.prototype} */
{
    MIN_PASSWORD_AGE_FACTOR: 60 * 60 * 1000,
    MAX_PASSWORD_AGE_FACTOR: 24 * 60 * 60 * 1000,

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

        this.passwordLength = $("input[name=pwdlength]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 100, value: 8, width: 50});
        this.passwordLengthState = $("input[name=usepwdlength]:checkbox", this.fieldset).change($.proxy(function() {
            var enabled = this.passwordLengthState.is(":checked:not(:disabled)");
            this.passwordLength.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.minPasswordAge = $("input[name=minpwdage]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 23, value: 1, width: 50});
        this.minPasswordAgeState = $("input[name=useminpwdage]:checkbox", this.fieldset).change($.proxy(function() {
            var enabled = this.minPasswordAgeState.is(":checked:not(:disabled)");
            this.minPasswordAge.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.maxPasswordAge = $("input[name=maxpwdage]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 999, value: 90, width: 50});
        this.maxPasswordAgeState = $("input[name=usemaxpwdage]:checkbox", this.fieldset).change($.proxy(function() {
            var enabled = this.maxPasswordAgeState.is(":checked:not(:disabled)");
            this.maxPasswordAge.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.passwordReminder = $("input[name=pwdreminder]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 100, value: 10, width: 50});
        this.passwordReminderState = $("input[name=usepwdreminder]:checkbox", this.fieldset).change($.proxy(function() {
            var enabled = this.passwordReminderState.is(":checked:not(:disabled)");
            this.passwordReminder.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.passwordHistory = $("input[name=pwdhistory]", this.fieldset).numberspinner({required: true, disabled: true, min: 1, max: 100, value: 3, width: 50});
        this.passwordHistoryState = $("input[name=usepwdhistory]:checkbox", this.fieldset).change($.proxy(function() {
            var enabled = this.passwordHistoryState.is(":checked:not(:disabled)");
            this.passwordHistory.numberspinner(enabled ? "enable" : "disable").numberspinner(enabled ? "enableValidation" : "disableValidation");
        }, this));

        this.firstTimeLoginResetPassword = $("input[name=ftlresetpwd]:checkbox", this.fieldset);
        this.uppercase = $("input[name=uppercase]:checkbox", this.fieldset);
        this.lowercase = $("input[name=lowercase]:checkbox", this.fieldset);
        this.numeric = $("input[name=numeric]:checkbox", this.fieldset);
        this.nonAlphaNumeric = $("input[name=nonalphanumeric]:checkbox", this.fieldset);
        this.denyLogin = $("input[name=denylogin]:checkbox", this.fieldset);

        this.usernameRegexEnabled = $("input[name=enableusernameregex]:checkbox", this.fieldset).change($.proxy(function() {
            var enabled = this.usernameRegexEnabled.is(":checked:not(:disabled)");
            this.usernameRegex.textbox(enabled ? "enable" : "disable").textbox(enabled ? "enableValidation" : "disableValidation").textbox("isValid");
        }, this));
        this.usernameRegex = $("input[name=usernameregex]", this.fieldset).textbox({required: true, validType: ["non_empty", "username_pattern"], disabled: true, missingMessage: window.R.string.COMPLIANCE_ERROR_BAD_PATTERN, invalidMessage: window.R.string.COMPLIANCE_ERROR_BAD_PATTERN, width: "75%"});

        this.fipsModeButton = $("input[name=fiprequired]", this.fieldset).switchbutton({onChange: $.proxy(this._onChange$FipsModeButton, 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)});
    },

    getMinPasswordLength: function() {
        return this.passwordLengthState.is(":checked") ? this.passwordLength.numberspinner("getValue") : null;
    },

    setMinPasswordLength: function(value) {
        this.passwordLengthState.prop("checked", value != null).change();
        if (value != null) {
            this.passwordLength.numberspinner("setValue", value);
        }
    },

    getMinPasswordAge: function() {
        return this.minPasswordAgeState.is(":checked") ? this.minPasswordAge.numberspinner("getValue") * this.MIN_PASSWORD_AGE_FACTOR : null;
    },

    setMinPasswordAge: function(value) {
        this.minPasswordAgeState.prop("checked", value != null).change();
        if (value != null) {
            this.minPasswordAge.numberspinner("setValue", parseInt(value) / this.MIN_PASSWORD_AGE_FACTOR);
        }
    },

    getMaxPasswordAge: function() {
        return this.maxPasswordAgeState.is(":checked") ? this.maxPasswordAge.numberspinner("getValue") * this.MAX_PASSWORD_AGE_FACTOR : null;
    },

    setMaxPasswordAge: function(value) {
        this.maxPasswordAgeState.prop("checked", value != null).change();
        if (value != null) {
            this.maxPasswordAge.numberspinner("setValue", parseInt(value) / this.MAX_PASSWORD_AGE_FACTOR);
        }
    },

    getPasswordExpirationNotificationDays: function() {
        return this.passwordReminderState.is(":checked") ? this.passwordReminder.numberspinner("getValue") : null;
    },

    setPasswordExpirationNotificationDays: function(value) {
        this.passwordReminderState.prop("checked", value != null).change();
        if (value != null) {
            this.passwordReminder.numberspinner("setValue", value);
        }
    },

    getEqualPasswordsHistoryLength: function() {
        return this.passwordHistoryState.is(":checked") ? this.passwordHistory.numberspinner("getValue") : null;
    },

    setEqualPasswordsHistoryLength: function(value) {
        this.passwordHistoryState.prop("checked", value != null).change();
        if (value != null) {
            this.passwordHistory.numberspinner("setValue", value);
        }
    },

    getUppercaseRequired: function() {
        return this.uppercase.is(":checked");
    },

    setUppercaseRequired: function(value) {
        this.uppercase.prop("checked", !!value);
    },

    getLowercaseRequired: function() {
        return this.lowercase.is(":checked");
    },

    setLowercaseRequired: function(value) {
        this.lowercase.prop("checked", !!value);
    },

    getNumericRequired: function() {
        return this.numeric.is(":checked");
    },

    setNumericRequired: function(value) {
        this.numeric.prop("checked", !!value);
    },

    getNonAlphaNumericRequired: function() {
        return this.nonAlphaNumeric.is(":checked");
    },

    setNonAlphaNumericRequired: function(value) {
        this.nonAlphaNumeric.prop("checked", !!value);
    },

    getNonCompliantPasswordDenied: function() {
        return this.denyLogin.is(":checked");
    },

    setNonCompliantPasswordDenied: function(value) {
        this.denyLogin.prop("checked", !!value);
    },

    getFirstTimeLoginResetPasswordRequired: function() {
        return this.firstTimeLoginResetPassword.is(":checked");
    },

    setFirstTimeLoginResetPasswordRequired: function(value) {
        this.firstTimeLoginResetPassword.prop("checked", !!value);
    },

    setUsernamePattern: function(value) {
        if (value != null) {
            this.usernameRegex.textbox("setValue", value);
            this.usernameRegexEnabled.prop("checked", true).change();
        } else {
            this.usernameRegexEnabled.prop("checked", false).change();
        }
    },

    getUsernamePattern: function() {
        return this.usernameRegexEnabled.is(":checked:not(:disabled)") ? this.usernameRegex.textbox("getValue") : null;
    },

    setFipsModeState: function(value) {
        var opts = this.fipsModeButton.switchbutton("options");
        var handler = opts.onChange;
        try {
            opts.onChange = $.noop;
            this.fipsModeButton.switchbutton(!!value ? "check" : "uncheck");
        } finally {
            opts.onChange = handler;
        }
    },

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

    _onChange$FipsModeButton: function(checked) {
        this.fipsModeButton.switchbutton("disable");
        this.listener.onChangeFipsMode(checked)
                .always($.proxy(function() { this.fipsModeButton.switchbutton("enable"); }, this));
    },

    _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();
    }
});
jscape.domain.ComplianceView.LISTENER = {
    onApply: $.noop,
    onDiscard: $.noop
};