/**
 * Class for dinamic form validate
 *
 * @author 	Preceptor educao a distncia <contato@preceptoread.com.br>
 * @version 2.0
 * @license	free for all
 */

/**
 * @constructor
 */
Validator = function( form ){

	this.validates 	   = [];
    this.errorMessages = [];
	this.form 		   = document.getElementById( form ) || document.forms[0];

	Validator.Event.on( this.form , "submit" , this.verify , this );
}


Validator.prototype = {

	/**
	 * Add validate to form
	 *
	 * @param string 	id
	 * @param function 	fn
	 * @param array 	data
	 * @param mixed		param
	 */
	add: function( id , fn , message , param )
	{
		if( !( id && fn ) ){
			alert('Wrong object arguments. Missing: id '+ id +'or func'+ fn +'\n\n');
			return false;
		}

		if( typeof param != 'object' && typeof param != 'undefined' ){
			param 	  = Array.prototype.slice.call(arguments, 3);
		}

		var values = {};
		values.id = id;
		values.fn = fn;
        values.message = message;
        values.param = param;

		if( !values.param ){
			values.param = null;
		}

        if( fn.mask ){
            fn.mask( id );
        }

        if( fn == Validate.notEmpty ){
        	this.markupNotEmpty(id);
        }

        if( fn == Validate.stringLength ){
            try{

               document.getElementById( id ).maxLength = !isNaN( param[param.length-1] ) ? param[param.length-1] : param[param.length-2];
            }catch( e ){
                //console.log( id );
            }
        }

		this.validates.push( values );
	},

    markupNotEmpty: function( value )
    {
        var labels = this.form.getElementsByTagName("label"),label;

        for ( k = 0; k < labels.length; k++ ){
            label = labels[k];
            if ( label.getAttribute('for') == value || label.getAttribute('htmlFor') == value ){
                if( label.innerHTML.indexOf( 'notEmpty') == -1  ){
                    label.innerHTML = "<span class='notEmpty'>*</span> " + label.innerHTML;
                }
            }
        }
    },

	/**
	 * Remove validate to form
	 *
	 * @param string 	field
	 * @param function 	fn
	 */
	remove: function( id , fn )
	{
		if( this.validates.length ){
			for(var i = this.validates.length-1; i > -1; i--){
				if(this.validates[i].id == id && this.validates[i].fn == fn){
					this.validates.splice( i , 1 );
				}
			}
		}
	},

	/**
	 * Verify all validates
	 */
	verify: function( ev )
	{
		Validator.Event.stopEvent( ev );

        this.preVerify();
        this.clearMessages();

        var i = 0,
            valid = true;

        for( i = 0; i < this.validates.length; i++ ){

        	if( this.inForm( this.validates[i].id ) ){
                var args = [],
                    el   = this.form.elements[this.validates[i].id];

                args[0] = typeof el.value == 'undefined' ? el : el.value;
                args 	= args.concat( this.validates[i].param );
                args	= this._valueByIdOrName( args );
                
                if( !this.validates[i].fn.apply( { element: el , validator: this }, args ) ){

                    if( valid ){
                        try{
                            el.focus();
                        }catch( e ){
                            
                        }
                    }

                    valid = false;
                	this.addError( i );
                }
            }
		}

        if( valid ){
        	this.success();
        }else{
            this.error();
        }
    },

    inForm: function( id )
  	{
	  	var n = this.form.elements.length;

	  	for ( var i = 0 ; i < n ; i++ ){
			if( this.form.elements[i].id == id || this.form.elements[i].name == id ){
				return true;
			}
		}
		return false;
  	},

  	_valueByIdOrName: function( param )
  	{
  		for( var i = 1; i < param.length; i++ ){

	  		var el = document.getElementById( param[i] );

	  		if( el ){
	  			param[i] = el.value;
	  		}else{

	  			var els = document.getElementsByName( param[i] );

	  			if( els.length ){
	  				param[i] = els[0].value;
	  			}
	  		}
  		}

  		return param;
  	},

    addError: function( index )
    {
  		var span 	   = document.createElement( 'SPAN' );
  		span.className = 'validate-error';
  		span.innerHTML = this.validates[index].message;

  		var el 	= document.getElementById( this.validates[index].id );

  		if( el ){
            el.parentNode.insertBefore( span , el.nextSibling );
        }else{
            alert( this.validates[index].message );
        }
    },

    clearMessages: function( childs )
    {
    	childs = childs || this.form.childNodes;

  		for( var i = 0; i < childs.length; i++ ){

  			var childsChilds = childs[i].childNodes;

  			if( childsChilds.length ){
  				this.clearMessages( childsChilds );
  			}

  			if( childs[i].className == 'validate-error' ){
  				try{
  					childs[i].parentNode.removeChild( childs[i] );
  				}catch( e ){}
  			}
  		}
    },
	/**
	 * Clear all validates
	 */
	clear: function()
	{
		this.validates = [];
        this.errorMessages = [];
	},

	/**
	 * overwrite
	 */
	success: function()
	{
		this.form.submit();
	},

    /**
	 * overwrite
	 */
	error: function()
	{
	},

    preVerify: function()
    {
		//overwrite
	}
}

Validate = {};

Validate.notEmpty = function( value, element )
{
  	if( !value.replace( /^\s*|\s*$/g , "" ) ){
		return false;
	}

	return true;
}

Validate.ckeckbox = function( value, name, limit )
{
	var els   = document.getElementsByName( name );
	var count = 0;
	limit     = limit || 1;

	for( var i = 0; i < els.length; i++ ){

		if( els[i].checked ){
			count++;
		}

		if( count == limit ){
			return true;
		}
	}

	return false;
}

Validate.radio = function( els )
{
	for( var i = 0; i < els.length; i++ ){

		if( els[i].checked ){
			return true;
		}
	}

	return false;
}


Validator.Event = {};
Validator.Event.listener = {};

Validator.Event.on = function( element , name , fn , subcribe )
{

    if( subcribe ){
        Validator.Event.listener[element.id] = fn;
        fn = function(e){
            return Validator.Event.listener[element.id].call( subcribe ,  e || window.event );
        }
    }

    if (element.addEventListener) {
        element.addEventListener( name, fn, false );
    } else if (element.attachEvent) {
        element.attachEvent( 'on' + name , fn );
    }
}

Validator.Event.stopEvent = function( event )
{
    if (event.preventDefault) {
        event.preventDefault();
        event.stopPropagation();
    } else {
        event.returnValue = false;
        event.cancelBubble = true;
    }
}

Validator.Event.key = function( ev )
{
    return ev.which || ev.keyCode;
}
