(function($){

  var validateRegexp = {
    alpha   : /^[A-Za-zА-ЯЁа-яё\s]+$/,
    alphanum: /^[A-Za-zА-ЯЁа-яё0-9-\s]+$/,
    num     : /^[0-9\s]+$/,
    tel     : /^[0-9-+*.()\s]+$/,
    email   : /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}[\s]*$/,
    //url   : /^([a-z0-9]{1,})([a-zа-яё0-9-._]*)\.([a-zа-яё]{2,6})$/;
    url     : /^(?:(?:https?):\/\/(?:[a-z0-9а-яё_-]{1,32}(?::[a-z0-9а-яё_-]{1,32})?@)?)?(?:(?:[a-z0-9а-яё-]{1,128}\.)+(?:com|net|org|mil|edu|arpa|ru|gov|biz|info|aero|inc|name|[a-zа-яё]{2,6})|(?!0)(?:(?!0[^.]|255)[0-9]{1,3}\.){3}(?!0|255)[0-9]{1,3})(?:\/[a-z0-9а-яё.,_@%&?+=\~\/-]*)?(?:#[^ \'\"&<>]*)?[\s]*$/i,
    street  : /^[A-Za-zА-ЯЁа-яё0-9-.\s]+$/,
    house   : /^[A-Za-zА-ЯЁа-яё0-9-/\s]+$/,
    housing : /^[A-Za-zА-ЯЁа-яё0-9-/\s]+$/,
    office  : /^[A-Za-zА-ЯЁа-яё0-9-\s]+$/
  };
  
  var validateError = '';
  var minValueIds = {
    'password': 6
  }
  var intervalValueIds = {
    'tel': '5-9'
  }
  
  var valid = true,
      error = '';
  
  var IE7_8 = false;
  if ( !$.support.opacity ){ var IE7_8 = true; }
  
  var settings,
      currentForm,
      validateElms,
      sendData;
       
  
  var methods = {
    init: function( options ){

      var defaults = {
        control: true,
        ajax: true,
        captcha: false,
        showWindows: true,
        ajaxURL: '',
        ajaxType: 'get',
        ajaxSendData: '',
        ajaxDataType: '',
        ajaxSuccess: function(){},
        beforeSubmit: function(){}
      };
      
      settings = $.extend( defaults, options );

      return this.each(function(){
      
        currentForm = $(this);
        validateElms = currentForm.find(':text.validate, :password.validate, textarea.validate, select.validate, .cusel');

        validateElms
        .bind('blur', function(){
          var $this = $(this);
          if ( $this.hasClass('required') || $this.hasClass('cusel') ) {
            methods.emptyValues($this);
          }
          else if ( $this.val() != '' ) {
            methods.validationForm($this);
          }
        })
        .bind('focus', function(){
          methods.removeNotice($(this).attr('id'));
        });
        
        currentForm.bind('submit', function(e){
          
          if ( settings.control ) {
            methods.removeNotice('all');
            valid = true;
            var requiredElms = validateElms.filter(':text.required, :password.required, textarea.required, select.required, .cusel');
            requiredElms.each(function(){
              methods.emptyValues($(this));
            });
          }
            
          if ( settings.ajax ) {
            e.preventDefault();
            if ( valid ) {
              sendData = currentForm.serialize();
              if ( settings.captcha ) {
                methods.createCaptcha(sendData);
              }
              else {
                settings.beforeSubmit(currentForm);
                methods.submitForm(sendData);
              }
            }
            //return false;  
          }  
          else {
            if ( valid ) {
              return true;  
            }
            else {
              return false;
            }
          }
            
        });
       
      });
      
    },
    emptyValues: function(el){
    
      if ( !el.is('select') && !el.hasClass('cusel') && el.val() == '' ) {
        error = 'Обязательное поле';
        valid = false;
        methods.createNotice(el, error);  
      }
      else if ( el.is('select') && !el.is(':selected') ) {
        error = 'Выберите вариант';
        valid = false;
        methods.createNotice(el, error);        
      }
      else if ( !el.is('select') && el.hasClass('cusel') ) {
        var cuselVal = el.find('input:hidden').val();
        if ( cuselVal == 0 || cuselVal == '' ) {
          error = 'Выберите вариант';
          valid = false;
          methods.createNotice(el, error);
        }
      }
      else {
        valid = methods.validationForm(el);
      }
    
    },
    validationForm: function(el){
      if ( el.is('select') ) {
        return;
      }
      if ( el.hasClass('alpha') ) {
        valid = methods.validAlpha(el);
      }
      if ( el.hasClass('alphanum') ) {
        valid = methods.validAlphaNum(el);
      }
      if ( el.hasClass('num') ) {
        valid = methods.validAlphaNum(el);
      }
      if ( el.hasClass('tel') ) {
        valid = methods.validTel(el);
      }
      if ( el.hasClass('email') ) {
        valid = methods.validEmail(el);
      }
      if ( el.hasClass('url') ) {
        valid = methods.validURL(el);
      }
      if ( el.hasClass('street') ) {
        valid = methods.validStreet(el);
      }
      if ( el.hasClass('house') ) {
        valid = methods.validHouse(el);
      }
      if ( el.hasClass('housing') ) {
        valid = methods.validHousing(el);
      }
      if ( el.hasClass('office') ) {
        valid = methods.validOffice(el);
      }
      if ( el.hasClass('interval') ) {
        var minVar = parseInt( minValueIds[ el.attr('id') ].slice(0, (minValueIds[ el.attr('id') ].indexOf('-'))) );
        var maxVar = parseInt( intervalValueIds[ el.attr('id') ].slice(intervalValueIds[ el.attr('id') ].indexOf('-')+1) );
        valid = methods.validInterval(el, minVar, maxVar);
      }
      if ( el.hasClass('min') ) {
        var minVar = minValueIds[ el.attr('id') ];
        valid = methods.validMin(el, minVar);
      }
      return valid;                                                                  
    },
    createCaptcha: function(){
      var currentFormId = currentForm.attr('id');
      
      var Captcha = $('<form class="form_code xxl_form" method="get" style="overflow:hidden;">'+
                    '<div class="form_item code"><label for="code">Введите проверочный код:</label>'+
                    '<div class="bg_inputs_box_right"><div class="bg_inputs_box_left"><div class="bg_inputs_right">'+       
                    '<div class="bg_inputs_left"><input type="text" id="code" name="code" /></div></div></div></div>'+
                    '</div><img src="/xxl_templ/php/secpic.php?'+Math.random()+'" width="100" height="60" alt="captcha" /><p class="err"></p>'+
                    '<div class="button button_form"><div><a href="#" class="submit_anchor">Отправить<span></span></a></div></div></form>');
 
      $.ModalWindow({ hide_method: 'remove', insert_html: Captcha, afterShow: function() {
        $('form.form_code').bind('submit', function(e){
          var code = $('#code').val();
          if ( !code ) { 
            return false; 
          }
          else {
            sendData = sendData + '&code=' + code;
            methods.submitForm(sendData); 
          }
          return false;  
        });         
      } });
  
    },
    removeCaptcha: function(){
       $.ModalWindow({ method: 'remove', hide_method: 'remove', hide_window: $('.form_code').parents('.modal') });
    },
    submitForm: function(){
      if ( !settings.ajaxURL ) {
        settings.ajaxURL = currentForm.attr('action');
      }
      if ( settings.captcha ) {
        var anim_load = $.Loader({ targetEl: $('#hey').find('.button_form'), css: {'right': -146 + 'px', 'top': 13 + 'px'} });
      }
      else {
        var anim_load = $.Loader({ targetEl: currentForm.find('.button_form'), css: {'right': -15 + 'px', 'top': 9 + 'px'} });
      }
      $.ajax({
        url: settings.ajaxURL,
        type: settings.ajaxType,
        data: sendData,
        dataType: settings.ajaxDataType,
        success: function(data){
          if ( settings.captcha ) {
            if ( data.status == 0 ) {
              $('p.err').html('Неверный код!');
              return false;
            }
            else {
              methods.removeCaptcha();
            }
          }
          
          $.Loader({ method: 'remove', remove_loader: anim_load });
          settings.ajaxSuccess(currentForm, data);
          
        },
        error: function(xhr, status){
          if (status != 'error'){
            $.crInfoWindow({w_text: 'Произошла ошибка. Попробуйте ещё раз.'});
          }
          $.Loader({ method: 'remove', remove_loader: anim_load });         
        }
      });      
    }, 
    createNotice: function(el, error){
      var elPos = el.position();
      var elPosLeft = elPos.left;
      var elPosTop = elPos.top;
      var Notice= $('<div class="notice_error" id=notice_error_'+el.attr('id')+'><div></div></div>');
      Notice.css({                  
        'left': (elPosLeft - 20) + el.outerWidth(true) * 2/3,
        'top': elPosTop - 20
      });
      el.parent().append(Notice);  
      Notice.find('div').text(error);
      Notice.bind('click', function(){
        var $this = $(this);
        $this.remove();
        var targetFocusElm = ($this.attr('id')).slice(13);
        $('#'+targetFocusElm).focus();
      });    
    },
    removeNotice: function(id){
      if ( id == 'all' ) {
        $('div.notice_error').remove();
      }
      else {
        $('#notice_error_' + id).remove();
      }      
    },
    validAlpha: function(el){
      if ( !validateRegexp['alpha'].test(el.val()) ) {
        error = 'Только буквы';
        methods.createNotice(el, error);
        return false;
      }
      return valid;        
    },
    validAlphaNum: function(el){
      if ( !validateRegexp['alphanum'].test(el.val()) ) {
        error = 'Только буквы и цифры';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validNum: function(el){
      if ( !validateRegexp['num'].test(el.val()) ) {
        error = 'Только цифры';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validTel: function(el){
      if ( !validateRegexp['tel'].test(el.val()) ) {
        if ( el[0].id == 'code_country' ) {
          error = 'Некорректный код страны';  
        }
        else if ( el[0].id == 'code_city' ) {
          error = 'Некорректный код города';
        }
        else {
          error = 'Некорректный телефон';
        }
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validEmail: function(el){
      var anim_load;
      if ( !validateRegexp['email'].test(el.val()) ) {
        error = 'Некорректный e-mail';
        methods.createNotice(el, error);
        valid = false;
      }
      else if ( el.hasClass('unique') ) {
        anim_load = $.Loader( {target_el: el.parents('.bg_inputs_box_right'), css: {'right': -20 + 'px', 'top': 12 + 'px'} } );
        $.ajax({
          url:'/xxl_func_lib/xxl_func_ajax.php',
          type:'get',
          data: { req_ajax: "email_repeat", email: el.val() },
          success: function(data){
            if ( data == 'no' ) {
              $.Loader({ method: 'remove', remove_loader: anim_load })
            }  
            else {
              error = 'E-mail занят';
              methods.createNotice(el, error);
              $.Loader({ method: 'remove', remove_loader: anim_load })
              valid = false;
            }
          }
        });
      }
      return valid;    
    },
    validURL: function(el){
      if ( !validateRegexp['url'].test(el.val()) ) {
        error = 'Некорректный адрес';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validStreet: function(el){
      if ( !validateRegexp['street'].test(el.val()) ) {
        error = 'Только буквы, цифры, ., -';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validHouse: function(el){
      if ( !validateRegexp['house'].test(el.val()) ) {
        error = 'Только буквы, цифры, -';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validHousing: function(el){
      if ( !validateRegexp['housing'].test(el.val()) ) {
        error = 'Только буквы, цифры, -, /';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validOffice: function(el){
      if ( !validateRegexp['office'].test(el.val()) ) {
        error = 'Только буквы, цифры, -';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validInterval: function(el, minVar, maxVar){
      if ( ( el.val().length < minVar ) || ( el.val().length > maxVar ) ) {
        error = 'Не менее ' + minVar + ' и не более ' + maxVar + ' символов';
        methods.createNotice(el, error);
        valid = false;
      }
      return valid;    
    },
    validMin: function(el, minVar){
      if ( el.val().length < minVar ) {
        error = 'Не менее ' + minVar + ' символов';
        methods.createNotice(el, error); 
        valid = false;           
      };
      return valid;      
    }            
  }
  
  $.fn.ValidateSubmitForm = function( method ) {
    
    if ( methods[method] ) {
      return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    } else {
      $.error( 'Метод ' +  method + ' неопределён в jQuery.ValidateSubmitForm' );
    }    
  
  };    

})( jQuery );
