function Validator( element_id, _settings, update ) {
    
    var errors = new Array();
    var element = element_id;
    var error_class = 'error';
    this.settings = _settings || {} ;
    this.check_duplicate_id = null ;
    this.error_duplicated_class = null;
    var prev_value = null;
    var update = update || null;
    var me = this;
    
    this.setStackPosition = function(i) {
        this.stuck_position = i;
        $(me.element).attr('vlist_id',i);
    };
    
    this.getStackPosition = function() {
        return this.stuck_position;
    }    
    
    this.proc = function( event ) {
        if ( prev_value == $(element).val() && me.element != '#feed_source_editor' ) return errors.length;
        
        prev_value = $(element).val();        
        errors = new Array();
        
        $(element).parent().children('p.'+me.error_class).css('display','none');
        $(element).parent().children('p.'+me.error_class).html('');
        
        $(me.settings).each(function(i,v) {
                        switch(v.name) {
                          case 'checkEmpty':
                              me.checkEmpty();
                          break;
                          case 'checkTooShort':
                              me.checkTooShort( v.value );
                          break;
                          case 'checkMinLength':
                              me.checkTooShort( v.value );
                          break;                          
                          case 'checkSelectBox':
                              me.checkSelectBox();
                          break;
                          case 'checkEmailSyntax':
                              me.checkEmail();
                          break;                          
                          case 'checkDuplicates':
                              me.checkDuplicates( v.value );
                          break;       
                          case 'checkDuplicatedSources':
                              me.check_duplicate_id = '#feed_source_editor';
                              $('p.error_duplicated_sources').css('display','none');
                              $('p.error_duplicated_sources').html('');
                              me.error_duplicated_class = 'error_duplicated_sources';
                              me.checkDuplicatedSources();
                          break;                            
                        }
        });
        
        me.showErrors();
        
        return errors.length;
    };    
    
    this.checkEmpty = function() {
        if ( $(element).val() == '' ) {
            errors.push( {"message":'Value can not be empty. Please fill the field.', "target":"" } );
        }
    };
    
    this.checkDuplicatedSources = function() {
        var values = new Array();
        var prev = null;
        var qnt = 0;
        $(me.check_duplicate_id+" fieldset:not('.more_fields') input[name='feed_sources[]']").each(
        function (i,el) {
            qnt++;
            if( 0 < $(el).val().length ) values.push( $(el).val() ); 
        });
        
        if( 1 == qnt) return;
        
        if ( 0 < values.length ) {
            values.sort();
            for ( i = 0; i <= values.length; i++ ){
              if ( prev == values[i] ) { 
                  errors.push( {"message":'Some of the following sources are duplicated.', "target":"error_duplicated_sources" });
                  break;
              }
              prev = values[i];
            }
        }
        
    };    
    
    this.checkTooShort = function(n) {
        if ( $(element).val().length <  n ) {
            errors.push( { "message":'Value is too short. Please fill at least '+n+ ' length value.', "target":"" } );
        }
    };    
    
    this.checkSelectBox = function() {
        if ( $(element).val() == 0 || $(element).val() == '' ) {
            errors.push( { "message":'Value from drop down box is not selected. Please select any option.',"target":""} );
        }
    };     

    this.checkEmail = function() {
        if ( $(element).val() != 'default value' && $(element).val() != '' 
             && !/^.+@.+\..{2,}$/i.test( $(element).val() ) ) {
            errors.push( { "message":'Email is not valid. Please check syntax of the email address.',"target":""} );
        }
    };      
    
    this.checkDuplicates = function( name ) {
        if ( $(element).val() != '' ) {
            $.post( url ,"call=Admin.checkDuplicates&field_name="+name+"&field_value="+$(element).val()+"&update="+update, function(response) {
             if( response.documentElement.tagName == 'error') {
                 alert( response.documentElement.firstChild.nodeValue );
             } if( response.documentElement.tagName == 'duplicated') {
                 me.showError( response.documentElement.firstChild.nodeValue );
             } else  {
                 //alert( "OK" );
             }
             });
         }
    };   

    this.showError = function( txt ) {
            var error_box = $(element).parent().children('p.'+me.error_class );
            $(error_box).html( txt );
            $(error_box).show();
    };    
    
    this.showErrors = function() {
        
        if ( errors.length > 0 ) {
            $(errors).each(function(i,v) {
                if ( 'error_duplicated_sources' == v.target ) {
                    var error_box = $('p.'+me.error_duplicated_class);
                } else {
                    var error_box = $(element).parent().children('p.'+me.error_class);
                }
                
                $(error_box).append( v.message + "<br/>" ).show();
                
            });
        }
    };
    
    this.validate = function() {
        return me.proc( null );
    }
    
    if ( $(element_id).attr('tagName') == 'SELECT' ) {
        $(element_id).change( this.proc ); 
        $(element_id).blur( this.proc );  
        me.error_class = 'error_select';
    } else { 
        $(element_id).blur( this.proc );
        me.error_class= 'error';
    }
    
    me.element = element_id;
    
};

function ValidationStack() {
    
    this.list = new Array();
    var me = this;
    
    this.add = function( element ) {
        me.list.push( element );
        return me.list.length - 1;
    }
    
    this.remove = function(i) {
        me.list[i] = null;
    }    
    
    this.validate = function() {
        var valid = true;
        //$("#global-form-error").hide();
        var errors = 0;
        if ( me.list.length > 0 ) {
            $(me.list).each(function(i,v) {
                if ( v != null ) { errors += v.validate(); }
            });
        }    
        
        if ( errors > 0  ) {
            //$("#global-form-error").html("Errors have occured. Please see each sections").show();
            //document.location = "#form-top";
            var valid = false;
        }
        return valid;
    }
}
