﻿if (iDevCenter == null)
    var iDevCenter = new Object();

if (iDevCenter.Validation == null)
    iDevCenter.Validation = new Object();

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.Delegate = function(object, method, params) {

    this.Invoke = function() {
        
        return method.call(object, params);
    }
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GetReference = function(name) {

    if (name == "")
        return undefined;

    var parts = name.split(/\./);
    var reference = window;
    
    for (var i = 0; i < parts.length; i++) {
        
        reference = reference[parts[i]];
        
        if (reference == undefined)
            return undefined;
    }

    if (reference == window)
        return undefined;
    
    return reference;        
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GetValue = function(control, trim) {

    if (typeof (control.value) != "string")
        throw "NOT_IMPLEMENTED";

    var value = control.value;

    if (trim)
        value = iDevCenter.Validation.Trim(value);

    return value;
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.Trim = function(value) {

    var matches = value.match(/^\s*(\S+(\s+\S+)*)\s*$/);
    
    if (matches == null) 
        return "";
    
    return matches[1];
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.CheckIsNotEmpty = function() {

    return (iDevCenter.Validation.GetValue(this.ControlToValidate, true) != '');
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.RequiredFieldValidator_Validate = function(onCompleteHandler) {

    this.IsValid = (iDevCenter.Validation.Trim(iDevCenter.Validation.GetValue(this.ControlToValidate)) != iDevCenter.Validation.Trim(this.InitialValue));
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.CompareValidator_Init = function() {

    this.ControlToCompare = document.getElementById(this.ControlToCompareID);
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.CompareValidator_Validate = function(onCompleteHandler) {

    this.IsValid = (iDevCenter.Validation.GetValue(this.ControlToValidate) == iDevCenter.Validation.GetValue(this.ControlToCompare));
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.RegularExpressionValidator_Validate = function(onCompleteHandler) {

    var value = iDevCenter.Validation.GetValue(this.ControlToValidate);
    
    if (iDevCenter.Validation.Trim(value) == "")
        return true;
    
    var matches = value.match(this.ValidationExpression);
    
    this.IsValid = (matches != null && value == matches[0]);
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.CustomValidator_Validate = function(onCompleteHandler) {

    if (this.CustomValidateFunction == "")
        return;
    
    var customValidateFunction = iDevCenter.Validation.GetReference(this.CustomValidateFunction);
    
    if (customValidateFunction == undefined) {
        
        this.IsValid = false;
        return;
    }
    
    var result = customValidateFunction.call(this, onCompleteHandler);
    
    if (result == false) // Validating async
        return false;
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GroupValidator_Constructor = function() {

    this.ValidatorIDs = new Array();
    this.Validators = new Array();
    this.InvalidValidator = null;
    
    this.RegisterValidator = function(validatorID) {

        this.ValidatorIDs.push(validatorID);
    }
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GroupValidator_Init = function() {

    for (var i = 0; i < this.ValidatorIDs.length; i++)
        this.Validators.push(iDevCenter.Validation.GetReference(this.ValidatorIDs[i]));
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GroupValidator_OnReset = function() {

    for (var i = 0; i < this.Validators.length; i++)
        this.Validators[i].OnReset();
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GroupValidator_OnError = function() {

    this.InvalidValidator.OnError();
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.GroupValidator_Validate = function(onCompleteHandler) {

    this.IsValid = true;
    this.InvalidValidator = null;

    return ValidateFrom.call(this, 0, onCompleteHandler);

    function ValidateFrom(startIndex, onCompleteHandler) {
    
        for (var i = startIndex; i < this.Validators.length; i++) {
            var validator = this.Validators[i];

            var result = validator.Validate.call(validator, new iDevCenter.Validation.Delegate(this, ValidateFromCompleted, [validator, i + 1, onCompleteHandler]));

            if (result == false) // Validating async
                return false;
            
            if (validator.IsValid)
                continue;
            
            this.IsValid = false;
            this.InvalidValidator = validator;
            
            break;
        }
    }
    
    function ValidateFromCompleted(params) {

        var validator = params[0];
        var startIndex = params[1];
        var onCompleteHandler = params[2];
        
        if (validator.IsValid) {

            var result = ValidateFrom.call(this, startIndex, onCompleteHandler);
            
            if (result == false)
                return false;
        }
        else {
            
            this.IsValid = false;
            this.InvalidValidator = validator;
        }
            
        if (onCompleteHandler != null)
            onCompleteHandler.Invoke();
    }
}

/// <summary>
/// 
/// </summary>
iDevCenter.Validation.Validator = function() {

    var _this = this;
    var _initialized = false;

    this.IsValid = true;

    /// <summary>
    /// 
    /// </summary>
    this.Init = function() {
       
        if (_initialized)
            return;

        this.Parent = window[this.ParentID];
        this.ControlToValidate = document.getElementById(this.ControlToValidateID);
        this.DefaultElement = document.getElementById(this.DefaultElementID);
        this.ErrorElement = document.getElementById(this.ErrorElementID);
        this.SuccessElement = document.getElementById(this.SuccessElementID);

        // TODO: Add support for multiple depenedent controls
        // TODO: Add support events other than 'change'

        if (this.Parent == undefined) {
            if (this.ControlToValidate != null) {
                
                if (document.addEventListener)
                    this.ControlToValidate.addEventListener("change", function() { ControlToValidate_OnChange.call(_this); }, false);
                    
                else if (document.attachEvent)
                    this.ControlToValidate.attachEvent("onchange", function() { ControlToValidate_OnChange.call(_this); });
            }
        }

        var initFunction = iDevCenter.Validation.GetReference(this.InitFunction);

        if (initFunction != undefined)
            initFunction.call(this);

        _initialized = true;
    }

    /// <summary>
    /// 
    /// </summary>
    this.GetDependentControls = function() {

        return [this.ControlToValidate];
    }

    /// <summary>
    /// 
    /// </summary>
    this.OnReset = function() {

        var onResetFunction = iDevCenter.Validation.GetReference(this.OnResetFunction);

        if (onResetFunction != undefined)
            if (onResetFunction.call(this) == false)
                return;

        var userOnResetFunction = iDevCenter.Validation.GetReference(this.UserOnResetFunction);

        if (userOnResetFunction != undefined)
            if (userOnResetFunction.call(this) == false)
                return;

        this.DefaultElement.style.display = "inline";
        this.SuccessElement.style.display = "none";
        this.ErrorElement.style.display = "none";
    }

    /// <summary>
    /// 
    /// </summary>
    this.OnError = function() {

        var onErrorFunction = iDevCenter.Validation.GetReference(this.OnErrorFunction);

        if (onErrorFunction != undefined)
            if (onErrorFunction.call(this) == false)
                return;

        var userOnErrorFunction = iDevCenter.Validation.GetReference(this.UserOnErrorFunction);

        if (userOnErrorFunction != undefined)
            if (userOnErrorFunction.call(this) == false)
                return;

        this.DefaultElement.style.display = "none";
        this.ErrorElement.style.display = "inline";
        this.SuccessElement.style.display = "none";
    }

    /// <summary>
    /// 
    /// </summary>
    this.OnSuccess = function() {

        var onSuccessFunction = iDevCenter.Validation.GetReference(this.OnSuccessFunction);

        if (onSuccessFunction != undefined)
            if (onSuccessFunction.call(this) == false)
                return;

        var userOnSuccessFunction = iDevCenter.Validation.GetReference(this.UserOnSuccessFunction);

        if (userOnSuccessFunction != undefined)
            if (userOnSuccessFunction.call(this) == false)
                return;

        this.DefaultElement.style.display = "none";
        this.ErrorElement.style.display = "none";
        this.SuccessElement.style.display = "inline";
    }

    /// <summary>
    /// 
    /// </summary>
    this.Validate = function(onCompleteHandler) {

        this.IsValid = true;

        var validateFunction = iDevCenter.Validation.GetReference(this.ValidateFunction);

        if (validateFunction == undefined)
            return;

        var result = validateFunction.call(this, onCompleteHandler);

        if (result == false) // Validating async
            return false;
    }

    /// <summary>
    /// 
    /// </summary>
    function ControlToValidate_OnChange() {

        this.OnReset();

        var userShouldValidateFunction = iDevCenter.Validation.GetReference(this.UserShouldValidateFunction);

        if (userShouldValidateFunction != undefined)
            if (userShouldValidateFunction.call(this) == false)
                return;
        
        var result = this.Validate(new iDevCenter.Validation.Delegate(this, OnValidateCompleted));
        
        if (result == false) // Validating async
            return false;

        OnValidateCompleted.call(this);

        function OnValidateCompleted() {

            if (this.IsValid)
                this.OnSuccess();
            else
                this.OnError();
        }
    }
}
