$( function() {
	$.fn.auth = function( ) {
		var Auth = function( layer ) {
			this.layer = layer;
			layer.data( 'Auth', this );

			this.fields = {
				inputLogin:		1,
				login:			1,
				inputPassword:	1,
				password:		1,
				enter:			1,
				genderMale:		1,
				genderFemale:	1,
				showLogin:		1,
				inputEmail:		1,
				email:			1,
				inputSecure:	1,
				secure:			1,
				code:			1,
				reloadSecure:	1,
				registration:	1,
				checkLogin:		1,
				checkPassword:	1,
				checkGender:	1,
				checkEmail:		1,
				checkSecure:	1,
				switchMode:		1
			};
			for( var i in this.fields ) this.fields[ i ] = layer.find( '.' + i );

			this.fields.switchMode.bind( 'mouseup', this, function( e ) { e.data.changeMode() } );
			this.fields.registration.bind( 'mouseup', this, function( e ) { e.data.changeRegMode() } );
			this.fields.reloadSecure.bind( 'mouseup', this,
				function( e ) { $.get( '/?action=code', function( data ) { e.data.reloadSecure( data ) }, 'text' ) } );

			this.checkField = { checkLogin: 1, checkPassword: 1 };
			this.fieldStatus = { checkLogin: false, checkPassword: false, checkGender: false, checkEmail: false, checkSecure: false };

			this.checkTimer = setInterval( function() { layer.data( 'Auth' ).checkFields() }, 300 );
			layer.find('.inputLogin, .inputPassword, .inputEmail, .inputSecure' ).bind( 'mouseup', function( e ) { $(this).find('input').focus() } );
			var input = layer.find('.inputLogin input, .inputPassword input, .inputEmail input, .inputSecure input' );
			input.bind( 'focus', this, function( e ) { e.data.inputFocus( e ) } );
			input.bind( 'blur', this, function( e ) { e.data.inputBlur( e ) } );
			input.bind( 'keyup', this, function( e ) { e.data.inputKeyup( e ) } );
			input.trigger( 'focus' );
			input.trigger( 'blur' );
			layer.find('.genderMale, .genderFemale').bind( 'mouseup', this, function( e ) { e.data.selectGender( e ) } );
			layer.find('.checkLogin, .checkPassword, .checkGender, .checkEmail, .checkSecure' ).bind( 'click', function( e ){ alert( $( e.target ).attr( 'title' ) ) } );
		};
		Auth.prototype = {
			mode: 'login',
			regMode: 'reg1',
			testLogin: new RegExp( "[^\\wА-Яа-яЁё\\+\\-\\~\\.\\s]" ),
			testEmail: new RegExp( "[\\w\\-]+(\\.[\\w\-]+)*\\@([\\w\-]+\\.)+\\w+" ),

			changeMode: function() {
				if( this.mode == 'login' ) {
					this.regMode = 'reg1';
					this.layer.removeClass( 'login' );
					this.layer.addClass( 'reg1' );
					this.mode = this.regMode;
					this.fields.checkLogin.addClass( 'error' );
					this.fields.checkLogin.attr( 'title', 'Проверяется...' );
					this.fields.checkPassword.addClass( 'error' );
					this.fields.checkPassword.attr( 'title', 'Проверяется...' );
					this.checkField = { checkLogin: 1, checkPassword: 1 };
					this.fields.checkGender.addClass( 'error' );
					this.fields.checkGender.attr( 'title', 'Пол персонажа не выбран' );
					this.fields.checkEmail.addClass( 'error' );
					this.fields.checkEmail.attr( 'title', 'Проверяется...' );
					this.fields.checkSecure.addClass( 'error' );
					this.fields.checkSecure.attr( 'title', 'Проверяется...' );
					this.checkField = { checkLogin: 1, checkPassword: 1 };
					this.layer.find('.genderMale, .genderFemale').removeClass('selected');
					this.gender = null;
					this.fieldStatus = { checkLogin: false, checkPassword: false, checkGender: false, checkEmail: false, checkSecure: false };
				}
				else{
					this.layer.removeClass( this.regMode );
					this.layer.addClass( 'login' );
					this.mode = 'login';
					this.fields.checkLogin.addClass( 'error' );
					this.fields.checkLogin.attr( 'title', 'Проверяется...' );
					this.fields.checkPassword.addClass( 'error' );
					this.fields.checkPassword.attr( 'title', 'Проверяется...' );
					this.checkField = { checkLogin: 1, checkPassword: 1 };
				}
			},

			changeRegMode: function() {
				if( this.regMode == 'reg1' ) {
					if( this.fieldStatus.checkLogin && this.fieldStatus.checkPassword && this.fieldStatus.checkGender ) {
						this.regMode = 'reg2';
						this.mode = 'reg2';
						this.layer.removeClass( 'reg1' );
						this.layer.addClass( 'reg2' );
						this.fields.showLogin.find('nobr').html( this.fields.login.val() );
						this.fields.showLogin.find('span').removeClass( 'male female' );
						this.fields.showLogin.find('span').addClass( this.gender );
						this.fields.email.val( '' );
						this.fields.email.find('span').css( { visibility: '' } );
						this.fields.secure.val( '' );
						this.fields.secure.find('span').css( { visibility: '' } );
						this.fields.registration.addClass( 'disabled' );
					}
				}
				else { // reg user
					if( !this.fieldStatus.checkLogin || !this.fieldStatus.checkPassword || !this.fieldStatus.checkGender ||
						!this.fieldStatus.checkEmail || !this.fieldStatus.checkSecure ) return;

					var layer = this.layer;
					var query = {
						action:		'reg',
						login:		this.fields.login.val(),
						password:	this.fields.password.val(),
						gender:		this.gender,
						email:		this.fields.email.val(),
						secure:		this.fields.secure.val(),
						code_id:	this.fields.secure.attr( 'code_id' )
					};
					$.post( '/', query, function( data ) { layer.data('Auth').regOnload( data ) }, 'json' );
				}
			},

			inputFocus: function( e ) {
				var input = $( e.target ).parent();
				input.find('span').css( { visibility: 'hidden' } );
			},

			inputBlur: function( e ) {
				var input = $( e.target ).parent();
				if( input.find('input').val() == '' )
					input.find('span').css( { visibility: '' } );
			},

			inputKeyup: function( e ) {
				var input = $( e.target ).parent();
				switch( input.attr( 'class' ) ) {
					case "inputLogin":
						this.checkField.checkLogin = 2;
						this.fieldStatus.checkLogin = false;
						this.fields.checkLogin.addClass( 'error' );
						this.fields.checkLogin.attr( 'title', 'Проверяется...' );
						this.fields.enter.find('input').attr( 'disabled', true );
						this.fields.enter.addClass( 'disabled' );
						this.fields.registration.addClass( 'disabled' );
					break;

					case "inputPassword":
						this.checkField.checkPassword = 2;
						this.fieldStatus.checkPassword = false;
						this.fields.checkPassword.addClass( 'error' );
						this.fields.checkPassword.attr( 'title', 'Проверяется...' );
						this.fields.enter.find('input').attr( 'disabled', true );
						this.fields.enter.addClass( 'disabled' );
						this.fields.registration.addClass( 'disabled' );
					break;

					case "inputEmail":
						this.checkField.checkEmail = 2;
						this.fieldStatus.checkEmail = false;
						this.fields.registration.addClass( 'disabled' );
					break;

					case "inputSecure":
						this.checkField.checkSecure = 2;
						this.fieldStatus.checkSecure = false;
						this.fields.registration.addClass( 'disabled' );
					break;
				}
			},

			selectGender: function( e ) {
				var gender = $(e.target);
				this.layer.find('.genderMale, .genderFemale').removeClass('selected');
				this.gender = gender.attr('class') == 'genderMale' ? 'male' : 'female';
				gender.addClass('selected');
				this.fields.checkGender.removeClass( 'error' );
				this.fields.checkGender.attr( 'title', 'Выбран ' + ( this.gender == 'male' ? 'мужской' : 'женский' ) + ' пол персонажа' );
				this.fieldStatus.checkGender = true;
				if( this.fieldStatus.checkLogin && this.fieldStatus.checkPassword )
					this.fields.registration.removeClass( 'disabled' );
			},

			checkFields: function( ) {
				try {
				var layer = this.layer;
				for( var field in this.checkField ) {
					if( this.checkField[ field ] == 1 ) {
						switch( field ) {
							case "checkLogin":
								var checkLogin = this.fields.checkLogin;
								checkLogin.addClass( 'error' );
								var login = this.fields.login.val().replace( /(^\s+|\s+$)/m, '' );
								if( login.length > 0 ) {
									if( login.length > 25 ) {
										checkLogin.attr( 'title', 'Длина имени персонажа не может быть больше 25 сиволов' );
									}
									else if( this.testLogin.test( login ) ) {
										checkLogin.attr( 'title', 'Имя персонажа содержит запрещённые символы' );
									}
									else {
										$.post( '/', { action: 'login', login: login },
											function( data ) { layer.data( 'Auth' ).checkOnload( 'checkLogin', data ) }, 'json' );
									}
								}
								else {
									checkLogin.attr( 'title', 'Имя персонажа не может быть пустым' );
								}
								this.fields.login.data( 'oldValue', this.fields.login.val() );
							break;

							case "checkPassword":
								var checkPassword = this.fields.checkPassword;
								checkPassword.addClass( 'error' );
								var password = this.fields.password.val();
								if( password.length < 6 ) {
									checkPassword.attr( 'title', 'Длина пароля не может быть меньше 6 символов.' );
								}
								else if( password.length > 15 ) {
									checkPassword.attr( 'title', 'Длина пароля не может быть больше 15 символов.' );
								}
								else {
									this.fieldStatus.checkPassword = true;
									if( this.mode == 'login' ) {
										if( this.fieldStatus.checkLogin ) {
											checkPassword.removeClass( 'error' );
											checkPassword.attr( 'title', 'Пароль введён корректно.' );
											this.fields.enter.find('input').attr( 'disabled', false );
											this.fields.enter.removeClass( 'disabled' );
										}
										else {
											checkPassword.attr( 'title', 'Пароль введён корректно, однако, такого персонажа не существует.' );
										}
									}
									else if( this.mode == 'reg1' ) {
										checkPassword.removeClass( 'error' );
										checkPassword.attr( 'title', 'Пароль введён корректно.' );
										if( this.fieldStatus.checkLogin && this.fieldStatus.checkGender )
											this.fields.registration.removeClass( 'disabled' );
									}
								}
								this.fields.password.data( 'oldValue', this.fields.password.val() );
							break;

							case "checkEmail":
								var checkEmail = this.fields.checkEmail;
								checkEmail.addClass( 'error' );
								var email = this.fields.email.val().replace( /(^\s+|\s+$)/m, '' );
								if( email.length > 0 ) {
									if( this.testEmail.test( email ) ) {
										checkEmail.removeClass( 'error' );
										checkEmail.attr( 'title', 'Адрес электронной почты введён корректно.' );
										this.fieldStatus.checkEmail = true;
										if( this.fieldStatus.checkSecure )
											this.fields.registration.removeClass( 'disabled' );
									}
									else {
										checkEmail.attr( 'title', 'Адрес электронной почты введён с ошибкой.' );
									}
								}
								else {
									checkEmail.attr( 'title', 'Не введён адрес электронной почты' );
								}
								this.fields.email.data( 'oldValue', this.fields.email.val() );

							break;

							case "checkSecure":
								var checkSecure = this.fields.checkSecure;
								checkSecure.addClass( 'error' );
								var secure = this.fields.secure.val();
								if( secure.length < 5 ) {
									checkSecure.attr( 'title', 'Код безопасности введён не полностью' );
								}
								else {
									$.post( '/', { action: 'check_code', id: this.fields.secure.attr('code_id'), code: this.fields.secure.val() },
										function( data ) { layer.data( 'Auth' ).checkOnload( 'checkSecure', data ) }, 'json' );
								}
								this.fields.secure.data( 'oldValue', this.fields.secure.val() );
							break;
						}
						delete this.checkField[ field ];
					}
					else if( this.checkField[ field ] == 2 ) {
						this.checkField[ field ] = 1;
					}
				}
				if( this.mode == 'login' || this.regMode == 'reg1' ) {
					if( !this.checkField.checkLogin && this.fields.login.val() != this.fields.login.data('oldValue') ) {
						this.checkField.checkLogin = 2;
						if( this.fields.login.val() != '' )
							this.fields.inputLogin.find('span').css( { visibility: 'hidden' } );
						this.fields.enter.addClass( 'disabled' );
						this.fields.enter.find('input').attr( 'disabled', true );
						this.fields.registration.addClass( 'disabled' );
					}
					if( !this.checkField.checkPassword && this.fields.password.val() != this.fields.password.data('oldValue') ) {
						this.checkField.checkPassword = 2;
						if( this.fields.password.val() != '' )
							this.fields.inputPassword.find('span').css( { visibility: 'hidden' } );
						this.fields.enter.addClass( 'disabled' );
						this.fields.enter.find('input').attr( 'disabled', true );
						this.fields.registration.addClass( 'disabled' );
					}
				}
				if( this.regMode == 'reg2' ) {
					if( !this.checkField.checkEmail && this.fields.email.val() != this.fields.email.data('oldValue') ) {
						this.checkField.checkEmail = 2;
						if( this.fields.email.val() != '' )
							this.fields.inputEmail.find('span').css( { visibility: 'hidden' } );
					}
					if( !this.checkField.checkSecure && this.fields.secure.val() != this.fields.secure.data('oldValue') ) {
						this.checkField.checkSecure = 2;
						if( this.fields.secure.val() != '' )
							this.fields.inputSecure.find('span').css( { visibility: 'hidden' } );
					}
				}
				}
				catch(e){ alert(e)};
			},

			checkOnload: function( filed, data ) {
				switch( filed ) {
					case 'checkLogin':
						var checkLogin = this.layer.find( '.checkLogin' );
						if( this.mode == 'login' ) {
							if( data.empty ) {
								checkLogin.addClass( 'error' );
								checkLogin.attr( 'title', 'Персонаж с таким именем не зарегистрирован.' );
								if( this.fieldStatus.checkPassword ) {
									this.fields.checkPassword.addClass( 'error' );
									this.fields.checkPassword.attr( 'title', 'Пароль введён корректно, однако, такого персонажа не существует.' );
								}
							}
							else if( data.blocked ) {
								checkLogin.addClass( 'error' );
								checkLogin.attr( 'title', 'Персонаж с таким именем заблокирован.' );
								if( this.fieldStatus.checkPassword ) {
									this.fields.checkPassword.addClass( 'error' );
									this.fields.checkPassword.attr( 'title', 'Пароль введён корректно, однако, такого персонажа не существует.' );
								}
							}
							else {
								checkLogin.removeClass( 'error' );
								checkLogin.attr( 'title', 'Вы можете зайти этим персонажем в игру.' );
								this.fieldStatus.checkLogin = true;
								if( this.fieldStatus.checkPassword ) {
									this.fields.checkPassword.removeClass( 'error' );
									this.fields.checkPassword.attr( 'title', 'Пароль введён корректно' );
									this.fields.enter.find('input').attr( 'disabled', false );
									this.fields.enter.removeClass( 'disabled' );
								}
							}
						}
						else {
							if( data.empty ) {
								checkLogin.removeClass( 'error' );
								checkLogin.attr( 'title', 'Вы можете зарегистритровать персонажа с таким именем.' );
								this.fieldStatus.checkLogin = true;
								if( this.mode == 'reg1' && this.fieldStatus.checkPassword && this.fieldStatus.checkGender )
									this.fields.registration.removeClass( 'disabled' );
							}
							else {
								checkLogin.addClass( 'error' );
								checkLogin.attr( 'title', 'Персонаж с таким именем уже зарегистрирован.' );
							}
						}
					break;

					case "checkSecure":
						if( data.correct ) {
							this.fields.checkSecure.removeClass( 'error' );
							this.fields.checkSecure.attr( 'title', 'Код безопасности введён правильно' );
							this.fieldStatus.checkSecure = true;
							if( this.fieldStatus.checkEmail )
								this.fields.registration.removeClass( 'disabled' );
						}
						else {
							this.fields.checkSecure.attr( 'title', 'Код безопасности введён с ошибкой.' );
						}
					break;
				}
			},

			regOnload: function( data ) {
				for( var i in data ) {
					switch( i ) {
						case "complete":
							this.layer.find( '.authForm' ).submit( );
						break;

						case "empty_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Имя персонажа не может быть пустым' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "spase_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Имя персонажа не может быть пустым' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "digital_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Имя персонажа не может состоять из одних цифр' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "short_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Имя персонажа не может быть короче 3 символов' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "long_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Имя персонажа не может быть длинее 25 символов' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "bad_symbol_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Имя персонажа не может содержать запрещенные символы' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "legacy_login":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkLogin = false;
							this.fields.checkLogin.attr( 'title', 'Персонаж с таким именем уже существует' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "short_password":
							this.fields.checkLogin.addClass( 'error' );
							this.fieldStatus.checkPassword = false;
							this.fields.checkPassword.attr( 'title', 'Пароль не может быть короче 6 символов' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "long_password":
							this.fields.checkPassword.addClass( 'error' );
							this.fieldStatus.checkPassword = false;
							this.fields.checkPassword.attr( 'title', 'Пароль не может быть длиннее 15 символов' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "bad_gender":
							this.fields.checkGender.addClass( 'error' );
							this.fieldStatus.checkGender = false;
							this.fields.checkGender.attr( 'title', 'Пол персонажа не выбран' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "bad_email":
							this.fields.checkEmail.addClass( 'error' );
							this.fieldStatus.checkEmail = false;
							this.fields.checkEmail.attr( 'title', 'Адрес электронной почты введён неправильно' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "bad_secure":
							this.fields.checkSecure.addClass( 'error' );
							this.fieldStatus.checkSecure = false;
							this.fields.checkSecure.attr( 'title', 'Код безопасности введён неправильно' );
							this.mode = this.regMode = 'reg1';
							this.layer.removeClass( 'login reg2' );
							this.layer.addClass( 'reg1' );
						break;

						case "wait_time":
							alert( "С вашего IP-адреса недавно остуществлялась регистрация. Пожалуйста, подождите 15 минут" );
						break;
					}
				}
			},

			reloadSecure: function( data ) {
				this.fields.secure.attr( 'code_id', data );
				this.fields.secure.val( '' );
				this.fields.code.css( { backgroundImage: 'url(/captcha?id='+data+')' } );
				this.fields.checkSecure.addClass( 'error' );
				this.fields.checkSecure.attr( 'title', 'Код безопасности введён не полностью' );
				this.fieldStatus.checkSecure = false;
			}
		};

		$(this).each( function( ) { $(this).data( 'Auth', new Auth( $(this) ) ) } );
	}
} );

