// определяем версию Mootools
var moo_version = (function() {
	var ver = '';
	if (typeof MooTools != 'undefined') {
		if (typeof window.Fx == 'undefined') {
			ver = 'core';
		} else {
			if (typeof window.Fx.Slide != 'undefined') {
				ver = 'advanced';
			} else {
				ver = 'full';
			}
		}
	}

	if (typeof Date.clone != 'undefined') {
		ver += ' extras';
	}

	return ver;
})();

if (!moo_version.match(/[^\s]/) || !moo_version.match(/core|full|advanced/))
	throw new Error('Mootools is not included.');

$type.element = function(element) {
	return $type(element) == 'element';
}
$type.textnode = function(element) {
	return $type(element) == 'textnode';
}
$type.whitespace = function(element) {
	return $type(element) == 'whitespace';
}
$type.arguments = function(element) {
	return $type(element) == 'arguments';
}
$type.array = function(element) {
	return $type(element) == 'array';
}
$type.object = function(element) {
	return $type(element) == 'object';
}
$type.string = function(element) {
	return $type(element) == 'string';
}
$type.number = function(element) {
	return $type(element) == 'number';
}
$type.date = function(element) {
	return $type(element) == 'date';
}
$type.bool = function(element) {
	return $type(element) == 'boolean';
}
$type.func = function(element) {
	return $type(element) == 'function';
}
$type.regexp = function(element) {
	return $type(element) == 'regexp';
}
$type.Class = function(element) {
	return $type(element) == 'class';
}
$type.collection = function(element) {
	return $type(element) == 'collection';
}

Array.implement({
			/**
			 * Функция, создания диапазона целых чисел
			 * 
			 * @return {Array}
			 */
			range : function() {
				if (this.length < 2)
					return false;
				var start = this[0];
				var stop = this[1];
				var nw = [];
				--start;
				while (++start <= stop) {
					nw.include(start);
				}
				return nw;
			},

			/**
			 * Находит наибольшее значение массива чисел
			 * 
			 * @return {Number} максимальное значение массива натуральных чисел
			 */
			getMax : function() {
				var max_value;
				for (var i = 0; i < this.length; i++) {
					if (!$chk(max_value)) {
						max_value = this[i].toInt();
					}
					if (this[i].toInt() > max_value) {
						max_value = this[i].toInt();
					}
				}
				return max_value;
			},

			/**
			 * Находит наименьшее значение массива чисел
			 * 
			 * @return {Number} минимальное занчение массива натуральных чисел
			 */
			getMin : function() {
				var min_value;
				for (var i = 0; i < this.length; i++) {
					if (!$chk(min_value)) {
						min_value = this[i].toInt();
					}
					if (this[i].toInt() < min_value) {
						min_value = this[i].toInt();
					}
				}
				return min_value;
			},

			/**
			 * @description Находит разницу массивов
			 * 
			 * @param {Array}
			 *            v вычитаемый массив
			 * @param {Boolean}
			 *            m в случае если тру, то возвращается только индекс
			 *            базового массива
			 * @return {Array} разницу массивов
			 */
			diff : function(v, m) {
				if (v.length) {
					var d = [], e = -1, h, i, j, k;
					for (i = this.length, k = v.length; i--;) {
						for (j = k; j && (h = this[i] !== v[--j]););
						h && (d[++e] = m ? i : this[i]);
					}
					return d;
				}
				return this;
			},

			/**
			 * @description Из массива объектов типа checkbox или radio находит
			 *              выделенные и возвращает в виде массива элементов
			 * 
			 * @return {Array} Выделенные элементы
			 */
			getChecked : function() {
				var chkd = [];
				for (var i = 0, len = this.length; i < len; i++) {
					if (this[i].get('tag') == 'input'
							&& (this[i].getProperty('type') == 'radio' || this[i]
									.getProperty('type') == 'checkbox')) {
						if (this[i].checked) {
							chkd.push(this[i]);
						}
					} else {
						break;
					}
				}
				return chkd;
			}
		});

Element.implement({

	/**
	 * Функция переключает класс hide - то есть переключает видимость элемента
	 * Нетрудно понять, что в стиля должен быть прописан стиль .hide { display:
	 * none; }
	 */
	toggle : function() {
		if (this.hasClass('hide')) {
			this.removeClass('hide');
		} else {
			this.addClass('hide');
		}
		return this;
	},

	/**
	 * Открывает элемент
	 */
	show : function() {
		if (this.hasClass('hide')) {
			this.removeClass('hide');
		}
		return this;
	},

	/**
	 * @description Скрывает элемент (добавляет класс hide)
	 */
	hide : function() {
		if (!this.hasClass('hide')) {
			this.addClass('hide');
		}
		return this;
	},

	/**
	 * Функция переключает элементу значение указанного аттрибута
	 * 
	 * @param {String}
	 *            attr атрибут, с которым работаем
	 * @param {Array}
	 *            values Значения атрибута, которые нужно менять
	 */
	toggleAttributes : function(attr, values) {
		if (attr == 'class') {
			if (this.hasClass(values[0])) {
				this.removeClass(values[0]);
				this.addClass(values[1]);
				return;
			}
			if (this.hasClass(values[1])) {
				this.removeClass(values[1]);
				this.addClass(values[0]);
				return;
			}
		} else {
			if ($(this).get(attr) == values[0]) {
				$(this).set(attr, values[1]);
			} else {
				$(this).set(attr, values[0]);
			}
		}
		return this;
	},

	/**
	 * Функция ресетает форму, в которой жестко прописаны <code>value</code>
	 * 
	 * @param {Element|String}
	 *            frm элемент формы, либо его идентфикатор
	 */
	resetForm : function() {
		if (!this.get('tag') !== 'form') {
			// если это не форма, то получается косяк
			return;
		}
		var control_elements = this.getElements('input, select, textarea');
		for (var i = 0, len = control_elements.length; i < len; i++) {
			if (control_elements[i].get('tag') == 'input'
					&& control_elements[i].getProperty('type') != 'reset'
					&& control_elements[i].getProperty('type') != 'submit') {
				if ((control_elements[i].getProperty('type') == 'radio' || control_elements[i]
						.getProperty('type') == 'checkbox')
						&& control_elements[i].checked) {
					control_elements[i].checked = false;
				}
				if (control_elements[i].getProperty('type') == 'text') {
					control_elements[i].value = '';
				}
			}
			if (control_elements[i].get('tag') == 'select') {
				control_elements[i].options[0].selected = true;
			}
			if (control_elements[i].get('tag') == 'textarea') {
				control_elements[i].value = '';
			}
		}
		return this;
	},
	/**
	 * Проверяем, является ли значение поля числом с плавающей запятой
	 * 
	 * @return {Boolean} правда, если значение поля - число в плавающей запятой;
	 *         ложь - в обратном случае
	 */
	isFloat : function() {
		var val = this.get('text');
		if (/^[-+]?[0-9]+(\.[0-9]+)?$/.test(val)) {
			return true;
		}
		return false;
	}
});

String.implement({
			/**
			 * Проверяем, является ли значение поля числом с плавающей запятой
			 * 
			 * @return {Boolean} правда, если значение поля - число в плавающей
			 *         запятой; ложь - в обратном случае
			 */
			isFloat : function() {
				var val = this;
				val += '';
				if (/^[-+]?[0-9]+(\.[0-9]+)?$/.test(val)) {
					return true;
				}
				return false;
			},
			/**
			 * Смотрим, четное ли число
			 * 
			 * @return {Boolean} правда, если значение поля - четное; ложь - в
			 *         обратном случае
			 */
			isOdd : function() {
				var num = this.toInt();
				return (num % 2) ? true : false;
			},
			/**
			 * Фукнция-транслитератор
			 * 
			 * @param {String}
			 *            string строка, которую нужно транслитирировать
			 * @return {String}
			 */
			transliterate : function(string) {
				string = this.trim();
				var cyr = ["Щ", "Ш", "Ч", "Ц", "Ю", "Я", "Ж", "А", "Б", "В",
						"Г", "Д", "Е", "Ё", "З", "И", "Й", "К", "Л", "М", "Н",
						"О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ь", "Ы", "Ъ",
						"Э", "Є", "Ї", "щ", "ш", "ч", "ц", "ю", "я", "ж", "а",
						"б", "в", "г", "д", "е", "ё", "з", "и", "й", "к", "л",
						"м", "н", "о", "п", "р", "с", "т", "у", "ф", "х", "ь",
						"ы", "ъ", "э", "є", "ї"];
				var lat = ["Shh", "Sh", "Ch", "C", "Ju", "Ja", "Zh", "A", "B",
						"V", "G", "D", "Je", "Jo", "Z", "I", "J", "K", "L",
						"M", "N", "O", "P", "R", "S", "T", "U", "F", "Kh", "'",
						"Y", "`", "E", "Je", "Ji", "shh", "sh", "ch", "c",
						"ju", "ja", "zh", "a", "b", "v", "g", "d", "je", "jo",
						"z", "i", "j", "k", "l", "m", "n", "o", "p", "r", "s",
						"t", "u", "f", "kh", "'", "y", "'", "e", "je", "ji"];

				for (var i = 0, len = cyr.length; i < len; i++) {
					string = string.replace(new RegExp(cyr[i], 'g'), lat[i]);
				}
				string = string.replace(
						/([qwrtpsdfghklzxcvbnmQWRTPSDFGHKLZXCVBNM]+)[jJ]e/g,
						"$1e");
				string = string.replace(
						/([qwrtpsdfghklzxcvbnmQWRTPSDFGHKLZXCVBNM]+)[jJ]/g,
						"$1'");
				string = string.replace(/([eyuioaEYUIOA]+)[Kk]h/g, "$1h");
				string = string.replace(/^kh/g, "h");
				string = string.replace(/^Kh/g, "H");
				string = string.replace(/[^a-zA-Z0-9_\.!?&']/g, "_");
				string = string.replace(/\n+/g, "_");

				return string;
			}
		});

/**
 * Функция подключения зависимостей
 */
function require() {
	var libs = [];
	var args = Array.prototype.slice.call(arguments);
	if (args.length) {
		if ($type(args[0]) == 'array') {
			libs = args[0];
		} else if ($type(args[0]) == 'string') {
			libs = args.filter(function(n) {
						return $type(n) == 'string';
					});
		} else {
			return false;
		}
	} else {
		return false;
	}
	var scripts_string = ''
	for (var i = 0, len = libs.length; i < len; i++) {
		if (libs[i].length) {
			scripts_string += '\n<scr' + 'ipt type="text/javascript" src="/js'
					+ libs[i].hyphenate().replace(/\-/g, '/') + '.js"></scr'
					+ 'ipt>';
		}
	}
	document.write(scripts_string);
}

/**
 * @description Обработчик событий вешается на элемент управления формой и
 *              запрещает вводить ничего, кроме цифр
 * 
 * @param {Event}
 *            e Событие
 */
function justNumber(e) {
	var event = new Event(e);
	// коды клавиш, печатающих цифры
	var number_key_codes = [48, 57].range().extend([96, 105].range()).extend([
			8, 9, 13, 17, 18, 37, 39, 46, 116]);

	if (!number_key_codes.contains(event.code) && !event.meta) {
		event.stop();
	}
}

/**
 * @description Активирует и деактивирует все сабмиты
 * 
 * @param {Boolean}
 *            pos Активировать все сабмиты или деактивировать
 */

var disableSubmits = null;

window.addEvent('domready', function() {
			// инициализируем функцию disableSubmits, чтобы она знала про все
			// кнопки-сабмиты на странице
			// находим все сабмиты на странице
			var submits = $$('input[type=submit]');
			disableSubmits = (function() {
				return function(pos) {
					$each(submits, function(subm) {
								if (pos) {
									subm.disabled = true;
								} else {
									subm.disabled = false;
								}
							});
				}
			})();
			// Находим все формы на странице
			var forms = $$('form');
			// циклимся по всем найденным формам
			$each(forms, function(form) {
						// айдишник формы, либо нулл
						var form_id = form.getProperty('id') || null;

						// при сабмите блокируем все кнопки-сабмиты
						form.addEvent('submit', function(e) {
									disableSubmits(true);
								});

						// если есть установки по проверке и у формы есть
						// айдишник
						if (typeof validation_data != 'undefined'
								&& $chk(form_id)
								&& $chk(validation_data[form_id])
								&& $chk(FormValidator)) {

							// инициализируем валидатор
							FormValidator.set(form, validation_data[form_id],
									true);
							// добавляем проверку формы при сабмите
							form.addEvent('submit', function(e) {
										if (!FormValidator.validate(form_id)) {
											new Event(e).stop();
											// освобождаем кнопки-сабмиты
											disableSubmits(false);
										}
									});
						}
					});
		});

/**
 * При выгрузке страницы енэйблим сабмиты обратно, чтобы нажатие "назад" не
 * приводило к показу страниц с отсутствующими сабмитами
 */
window.addEvent('unload', function() {
			disableSubmits(false);
		});