//****************************************************************
// This section provides base objects for Validation
//***************************************************************
if (!SIGI || !SIGI.Parsing || !SIGI.TooltipControllerObject) {
    throw ("SIGI.Validation depends on the following scripts. Please make sure these are included.\nSIGI.js, SIGI.Parsing, SIGI.ToolTip");
}
SIGI.Validation = {};
SIGI.Validation.PageValidators = new Array();
SIGI.Validation.PageValidators.add = function(validator) { this.push(validator); };
SIGI.Validation.Errors = new Array();


SIGI.Validation.Validate = function(showSummary) {
    var valid = true;
    SIGI.Validation.Errors = new Array();
    for (var i = 0; i < SIGI.Validation.PageValidators.length; i++) {
        var validator = SIGI.Validation.PageValidators[i]; //
        if (validator && validator.validate) {
            valid = validator.validate() && valid;
            if (!validator.isValid) {
                SIGI.Validation.Errors.push(new SIGI.Validation.ErrorObject(validator.control, validator.severity, validator.errorMessage));
            }
        }
    }
    if (!valid && showSummary) {
        return SIGI.Validation.displayErrors();
    }
    return valid;
}

SIGI.Validation.add_onSummaryContinue = function(functionPointer) {
    this._onSummaryContinue = functionPointer;
}

SIGI.Validation._fire_onSummaryContinue = function(returnValue) {
    if (this._onSummaryContinue) {
        var eventArgs = returnValue; //this is the return from the dialog
        var sender = this;
        return eval("this._onSummaryContinue(sender, eventArgs)");
    }
}


SIGI.Validation.displayErrors = function() {
    if (SIGI.Browser.isIE) {
        var ret = SIGI.showModalDialog(SIGI.getClientThemePath() + "/Pages/SIGI.Validation.Summary.htm", SIGI.Validation.Errors, 428, 475);

        if (ret) {
            if (ret != "continue") {
                document.getElementById(ret);
                SIGI.setFocus(ret);
                return false;
            }
            else {
                SIGI.Validation._fire_onSummaryContinue(ret);
                return true;
            }
        }
    }
}


SIGI.Validation.onbeforedeactivate = function() {
    var validator = event.srcElement.validationObject;
    if (validator && validator.validate) {
        if (!validator.validate()) {
            if ((validator.severity == "information") && (event.srcElement == SIGI.Tooltip.currentElement)) {
                event.returnValue = true;
                return true;
            }
            SIGI.Tooltip.showForValidation(event.srcElement, validator.errorMessage, validator.severity, validator.align);
            event.returnValue = false;
            return false;
        }
    }
    return true;
}


//****************************************************************
// This section provides base objects for Validation
//***************************************************************
function ErrorObject(control, severity, errorMessage) {
    this.Base();
    this.control = (control) ? control : null;
    this.severity = (typeof (severity) != "undefined") ? severity : "critical";
    this.errorMessage = (errorMessage) ? errorMessage : "Validation failed";
}
ErrorObject.inherits(SIGI.Base);
SIGI.Validation.ErrorObject = ErrorObject;
ErrorObject = null;




function BaseValidatorObject(control, severity, errorMessage, align) {
    this.ErrorObject(control, severity, errorMessage);
    this.align = (align) ? align : "bottom";
    this.enabled = true;
    this.isValid = true;
    this.label = null;

    if (this.control) {
        if (this.control.className && this.control.className == "DropDownList") {
            if (this.control.dropDownListObject) {
                this.control = this.control.dropDownListObject._textbox;
            }
        }
        if (this.control.label) {
            if (typeof this.control.label == "string") {
                this.label = document.getElementById(control.label);
                this.control.label = this.label;
            } else {
                this.label = this.control.label;
            }
        }
    }
}
BaseValidatorObject.inherits(SIGI.Validation.ErrorObject);
BaseValidatorObject.prototype.validate = function() {
    return this.isValid;
}
BaseValidatorObject.prototype.colorLabel = function() {
    if (this.label) {
        if (this.isValid) {
            if (this.disabled) {
                this.label.className = "DisabledLabel";
            }
            else {
                this.label.className = "FormLabel";
            }
        } else {
            if (this.severity == "information")
                this.label.className = "FormLabel";
            else
                this.label.className = "ErrorLabel";
        }
    }
}
BaseValidatorObject.prototype.getValue = SIGI.getValue;
BaseValidatorObject.prototype.getValueRecursive = SIGI.getValueRecursive;

BaseValidatorObject.prototype.setProperty = function(propertyValue) {
    switch (propertyValue.trim()) {
        case "true": case "false":
            this.enabled = propertyValue.qtrim().toBoolean();
            break;
        case "critical": case "information": case "exclamation": case "help": case "question":
            this.severity = propertyValue.qtrim();
            break;
        default:
            var re = /\s*(\w+)\s*\(\s*((?:"[^"]*"|'[^']*'|[^'"\)])*)\s*\)\s*/g;
            if (re.test(propertyValue)) {
                re.exec(propertyValue);
                switch (RegExp.$1.toLowerCase()) {
                    case "severity":
                        this.severity = propertyValue.qtrim();
                        break;
                    case "msg":
                        this.errorMessage = RegExp.$2.qtrim();
                        break;
                    default:
                        this.handleProperty(RegExp.$1.toLowerCase(), RegExp.$2)
                }
            } else {
                this.handleProperty(null, propertyValue);
            }
    }
}
BaseValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) { }
BaseValidatorObject.prototype.parseProperties = function(propertiesText) {
    var re = /((?:"[^"]*"|'[^']*'|[^'"\s])*)(?:\s|$)/g;
    var matches = propertiesText.match(re);
    for (var i = 0; i < matches.length; i++) {
        this.setProperty(matches[i].trim());
    }
}
SIGI.Validation.BaseValidatorObject = BaseValidatorObject;
BaseValidatorObject = null;




function RequiredValidatorObject(control, required, severity, errorMessage, align) {
    this.BaseValidatorObject(control, severity, errorMessage, align);
    this.enabled = (required != null) ? required : true;
    this.errorMessage = (errorMessage) ? errorMessage : "Field is required.";
}
RequiredValidatorObject.inherits(SIGI.Validation.BaseValidatorObject);
RequiredValidatorObject.prototype.validate = function() {
    if (this.enabled) {
        //TODO abstract this code...
        var value = this.getValue(this.control);
        if ((this.control.type) && (this.control.type.toLowerCase() == "radio"))
            value = $SIGIfind(this.control.id).get_group().get_value();
        if (value == null) {
            this.isValid = false;
        } else {
            this.isValid = (value.length > 0);
        }
        this.colorLabel();
    }
    return this.isValid;
}
SIGI.Validation.RequiredValidatorObject = RequiredValidatorObject;
RequiredValidatorObject = null;


function DataTypeValidatorObject(control, dataType, severity, errorMessage, align) {
    this.BaseValidatorObject(control, severity, errorMessage, align);
    this.dataType = (dataType) ? dataType : "string";
    this.errorMessage = (errorMessage) ? errorMessage : "DataType is invalid";
    this.cutOffYear = 2029;
    this.century = 2000;
    this.decimalchar = ".";
    this.groupchar = ",";
    this.digits = 2;
    this.dateorder = "mdy";
}
DataTypeValidatorObject.inherits(SIGI.Validation.BaseValidatorObject);
DataTypeValidatorObject.prototype.validate = function() {
    this.isValid = true;
    if (this.enabled) {
        var value;
        if (((this.control.className.toLowerCase() == "maskededit") && (this.control.parentElement.className.toLowerCase() == "calendarcontrol")) || ((this.control.className.toLowerCase() == "maskededit") && (this.dataType == "date")))
            value = $SIGIfind(this.control.id).get_textWithMask();
        else
            value = this.getValue(this.control);
        if ((value) && ($SIGIfind(this.control.id)) &&($SIGIfind(this.control.id).get_text() != "")) {
            value = this.convert(value, this.dataType);
            this.isValid = (value == null) ? false : true;
        }
        this.colorLabel();
    }
    return this.isValid;
}
DataTypeValidatorObject.prototype.convert = function(text, dataType) {
    function GetFullYear(element, year) {
        return (year + parseInt(element.century)) - ((year < element.cutoffyear) ? 0 : 100);
    }
    var num, cleanInput, m, exp;
    switch (dataType) {
        case "integer":
            text = text.toString().replace(",", "")
            exp = /^\s*[-\+]?\d+\s*$/;
            if (text.match(exp) == null)
                return null;
            num = parseInt(text, 10);
            return (isNaN(num) ? null : num);
        case "double":
            exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + this.decimalchar + "(\\d+))?\\s*$");
            m = text.match(exp);
            if (m == null)
                return null;
            cleanInput = m[1] + (m[2].length > 0 ? m[2] : "0") + "." + m[4];
            num = parseFloat(cleanInput);
            return (isNaN(num) ? null : num);
        case "currency":
            exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + this.groupchar + ")*)(\\d+)"
						+ ((this.digits > 0) ? "(\\" + this.decimalchar + "(\\d{1," + this.digits + "}))?" : "")
						+ "\\s*$");
            m = text.match(exp);
            if (m == null)
                return null;
            var intermed = m[2] + m[5];
            cleanInput = m[1] + intermed.replace(new RegExp("(\\" + this.groupchar + ")", "g"), "") + ((this.digits > 0) ? "." + m[7] : 0);
            num = parseFloat(cleanInput);
            return (isNaN(num) ? null : num);
        case "date":
            var yearFirstExp = new RegExp("^\\s*((\\d{4})|(\\d{2}))([-./])(\\d{1,2})\\4(\\d{1,2})\\s*$");
            m = text.match(yearFirstExp);
            var day, month, year;
            if (m != null && (m[2].length == 4 || this.dateorder == "ymd")) {
                day = m[6];
                month = m[5];
                year = (m[2].length == 4) ? m[2] : GetFullYear(parseInt(m[3], 10))
            }
            else {
                if (this.dateorder == "ymd") {
                    return null;
                }
                var yearLastExp = new RegExp("^\\s*(\\d{1,2})([-./])(\\d{1,2})\\2((\\d{4})|(\\d{2}))\\s*$");
                m = text.match(yearLastExp);
                if (m == null) {
                    return null;
                }
                if (this.dateorder == "mdy") {
                    day = m[3];
                    month = m[1];
                }
                else {
                    day = m[1];
                    month = m[3];
                }
                year = (m[5].length == 4) ? m[5] : GetFullYear(this, parseInt(m[6], 10))
            }
            month -= 1;
            var date = new Date(year, month, day);
            return (typeof (date) == "object" && year == date.getFullYear() && month == date.getMonth() && day == date.getDate()) ? date.valueOf() : null;
        default:
            return text.toString();
    }
}
DataTypeValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) {
    switch (propertyName) {
        case "type":
            this.dataType = propertyValue.qtrim().toLowerCase();
            break;
        default:
            this.BaseValidatorObject.prototype.handleProperty.apply(this, arguments);
    }
}
SIGI.Validation.DataTypeValidatorObject = DataTypeValidatorObject;
DataTypeValidatorObject = null;




function CompareValidatorObject(control, valueToCompare, dataType, severity, errorMessage, align) {
    this.DataTypeValidatorObject(control, dataType, severity, errorMessage, align);
    this.controlToCompare = null;
    this.valueToCompare = null;
    this.operator = "Equals"

    if (typeof (valueToCompare) == "object") {
        this.controlToCompare = valueToCompare;
    } else {
        if (valueToCompare) this.valueToCompare = valueToCompare;
    }
}
CompareValidatorObject.inherits(SIGI.Validation.DataTypeValidatorObject);
CompareValidatorObject.prototype.validate = function() {
    this.isValid = true;
    if (this.enabled != false) {
        var value = this.getValue(this.control);
        if (value != null) {
            if (value.trim().length == 0)
                return true;
            if (this.controlToCompare != null) {
                this.valueToCompare = this.getValue(this.controlToCompare);
            }
            if (this.valueToCompare != null && typeof (this.valueToCompare) == "string") {
                this.isValid = this.compare(value, this.valueToCompare, this.operator, this.dataType);
            }
        }
        this.colorLabel();
    }
    return this.isValid;
}
CompareValidatorObject.prototype.compare = function(leftText, rightText, operator, dataType) {
    var op1, op2;
    if ((op1 = this.convert(leftText, dataType)) == null)
        return false;
    if (operator == "DataTypeCheck")
        return true;
    if ((op2 = this.convert(rightText, dataType)) == null)
        return true;
    switch (operator) {
        case "NotEqual":
            return (op1 != op2);
        case "GreaterThan":
            return (op1 > op2);
        case "GreaterThanEqual":
            return (op1 >= op2);
        case "LessThan":
            return (op1 < op2);
        case "LessThanEqual":
            return (op1 <= op2);
        default:
            return (op1 == op2);
    }
}
CompareValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) {
    switch (propertyName) {
        case "compare":
            this.valueToCompare = propertyValue.qtrim();
            try {
                var element = document.getElementById(this.valueToCompare);
                if (element != null) this.controlToCompare = element;
            } catch (exc) { }
            break;
        case "operator":
            this.operator = propertyValue.qtrim();
            break;
        default:
            this.DataTypeValidatorObject.prototype.handleProperty.apply(this, arguments);
    }
}
SIGI.Validation.CompareValidatorObject = CompareValidatorObject;
CompareValidatorObject = null;





function RangeValidatorObject(control, minimumValue, maximumValue, dataType, severity, errorMessage, align) {
    this.CompareValidatorObject(control, null, dataType, severity, errorMessage, align);
    this.minimumValue = (minimumValue) ? minimumValue : null;
    this.maximumValue = (maximumValue) ? maximumValue : null;
    this.dataType = (dataType) ? dataType : "string";
}
RangeValidatorObject.inherits(SIGI.Validation.CompareValidatorObject);
RangeValidatorObject.prototype.validate = function() {
    this.isValid = true;
    if (this.enabled != false) {
        var value = this.getValue(this.control);
        if ((value != null) && (value.qtrim() != "")) {
            this.isValid = this.compare(value, this.minimumValue, "GreaterThanEqual", this.dataType);
            if (this.isValid) {
                this.isValid = this.compare(value, this.maximumValue, "LessThanEqual", this.dataType);
            }
        }
        this.colorLabel();
    }
    return this.isValid;
}
RangeValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) {
    switch (propertyName) {
        case "min":
            this.minimumValue = propertyValue.qtrim();
            break;
        case "max":
            this.maximumValue = propertyValue.qtrim();
            break;
        default:
            this.CompareValidatorObject.prototype.handleProperty.apply(this, arguments);
    }
}
SIGI.Validation.RangeValidatorObject = RangeValidatorObject;
RangeValidatorObject = null;



function RegularExpressionValidatorObject(control, expression, options, severity, errorMessage, align) {
    this.BaseValidatorObject(control, severity, errorMessage, align);
    this.errorMessage = (errorMessage) ? errorMessage : "Value is not formatted correctly";
    this.expression = (expression) ? expression : null;
    this.options = (options) ? options : "gi";
}
RegularExpressionValidatorObject.inherits(SIGI.Validation.BaseValidatorObject);
RegularExpressionValidatorObject.prototype.validate = function() {
    this.isValid = true;
    if (this.enabled) {
        var value = this.getValue(this.control);
        if (value) {
            var template = new RegExp(this.expression, this.options)
            this.isValid = template.test(value);
        }
        this.colorLabel();
    }
    return this.isValid;
}
RegularExpressionValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) {
    switch (propertyName) {
        case "expression":
            this.expression = propertyValue.qtrim();
            break;
        case "options":
            this.options = propertyValue.qtrim();
            break;
        default:
            this.BaseValidatorObject.prototype.handleProperty.apply(this, arguments);
    }
}
SIGI.Validation.RegularExpressionValidatorObject = RegularExpressionValidatorObject;
RegularExpressionValidatorObject = null;



function ValuesValidatorObject(control, values, severity, errorMessage, align) {
    this.BaseValidatorObject(control, severity, errorMessage, align);

    if (values)
        this.values = values;
    else
        this.values = new Array();
}
ValuesValidatorObject.inherits(SIGI.Validation.BaseValidatorObject);
ValuesValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) {
    switch (propertyName) {
        case "inlist":
            this.values = propertyValue.replace(/'/g, "").split(",");
            this.listType = "valid";
            break;
        case "notinlist":
            this.values = propertyValue.replace(/'/g, "").split(",");
            this.listType = "invalid";
            break;
        default:
            this.BaseValidatorObject.prototype.handleProperty.apply(this, arguments);
    }
}
ValuesValidatorObject.prototype.validate = function() {
    this.isValid = true;
    if (this.enabled) {
        var value = this.getValue(this.control);
        if (value) {
            if (this.listType == "valid") {
                this.isValid = false;
                for (var i = 0; i < this.values.length; i++) {
                    var leftText = this.values[i];
                    if (leftText) {
                        this.isValid = (leftText.toString().toLowerCase() == value.toString().toLowerCase())
                        if (this.isValid) return this.isValid;
                    }
                }
            }
            else {
                this.isValid = true;
                for (var i = 0; i < this.values.length; i++) {
                    var leftText = this.values[i];
                    if (leftText) {
                        this.isValid = !(leftText.toString().toLowerCase() == value.toString().toLowerCase())
                        if (!this.isValid) return this.isValid;                        
                    }
                }
            }
        }
        this.colorLabel();
    }
    return this.isValid;
}
SIGI.Validation.ValuesValidatorObject = ValuesValidatorObject;
ValuesValidatorObject = null;


function CustomValidatorObject(clientFunction, severity, errorMessage) {
    this.BaseValidatorObject(null, severity, errorMessage, null);
    this.clientFunction = (clientFunction) ? clientFunction : null;
}
CustomValidatorObject.inherits(SIGI.Validation.BaseValidatorObject);
CustomValidatorObject.prototype.validate = function() {
    if (this.enabled && this.clientFunction) {
        if (typeof this.clientFunction == "string") {
            if (window[this.clientFunction]) {
                this.clientFunction = window[this.clientFunction];
            }
        }
        this.isValid = SIGI.Convert.toBoolean(this.clientFunction());
        this.colorLabel();
    }
    return this.isValid;
}
CustomValidatorObject.prototype.handleProperty = function(propertyName, propertyValue) {
    switch (propertyName) {
        case "client":
            this.clientFunction = propertyValue.qtrim();
            if (this.clientFunction.length > 0) {
                if (window[this.clientFunction]) {
                    this.clientFunction = window[this.clientFunction];
                } else {
                    this.clientFunction = function() {
                        return eval("'" + this.clientFunction + "'")
                    }
                }
            } else {
                this.clientFunction = null;
            }
            break;
        default:
            this.BaseValidatorObject.prototype.handleProperty.apply(this, arguments);
    }
}
SIGI.Validation.CustomValidatorObject = CustomValidatorObject;
CustomValidatorObject = null;



function ControlValidatorObject(control) {
    this.BaseValidatorObject(control);
    this.StyleParser();
    this.validators = new Array();

    if (this.control) {
        if (typeof (this.control.validation) == "string") {
            var validation = this.control.validation;
            if (validation) this.parseProperties(validation);
        }
        this.control.validationObject = this;
        this.control.attachEvent("onbeforedeactivate", SIGI.Validation.onbeforedeactivate);
    }
}
ControlValidatorObject.inherits(SIGI.Parsing.StyleParser);
ControlValidatorObject.inherits(SIGI.Validation.BaseValidatorObject);
ControlValidatorObject.prototype.setProperty = function(propertyName, value) {
    if (value) value = value.trim();
    var validator = null;
    switch (propertyName.toLowerCase()) {
        case "required":
            validator = new SIGI.Validation.RequiredValidatorObject(this.control);
            break;
        case "datatype":
            validator = new SIGI.Validation.DataTypeValidatorObject(this.control);
            break;
        case "compare":
            validator = new SIGI.Validation.CompareValidatorObject(this.control);
            break;
        case "range":
            validator = new SIGI.Validation.RangeValidatorObject(this.control);
            break;
        case "regularexpression":
            validator = new SIGI.Validation.RegularExpressionValidatorObject(this.control);
            break;
        case "values":
            validator = new SIGI.Validation.ValuesValidatorObject(this.control);
            break;
        case "custom":
            validator = new SIGI.Validation.CustomValidatorObject();
            break;
    }
    if (validator) {
        validator.parseProperties(value);
        this.validators.push(validator);
    }
}
ControlValidatorObject.prototype.validate = function() {

    if ((this.control) && (this.control.disabled) && (!toBoolean(this.control.validateDisabled))) return true;
    for (var i = 0; i < this.validators.length; i++) {
        validator = this.validators[i];
        if (validator) {
            this.isValid = validator.validate();
            if (!this.isValid) {
                this.align = validator.align;
                this.severity = validator.severity;
                this.errorMessage = validator.errorMessage;
                this.colorLabel();
                return false;
            }
        }
    }
    this.colorLabel();
    return this.isValid;
}
SIGI.Validation.ControlValidatorObject = ControlValidatorObject;
ControlValidatorObject = null;

