/**
 * Смотрим, четное ли число
 * 
 * @param {Number}
 *            num Четное или нечетное число
 */
function isOdd(num) {
	var num = num.toInt();
	return (num % 2) ? true : false;
}

/**
 * Функция, создания диапазона целых чисел
 * 
 * @param {Number}
 *            start наименьшее значение
 * @param {Number}
 *            stop наибольшее значение
 * 
 * @return {Array}
 */
Array.prototype.range = function() {
	var start = this[0];
	var stop = this[1];
	var nw = [];
	--start;
	while (++start <= stop) {
		nw.include(start);
	}
	return nw;
}
/**
 * Находит наибольшее значение массива чисел
 * 
 * @return {Number} максимальное значение массива натуральных чисел
 */
Array.prototype.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} минимальное занчение массива натуральных чисел
 */
Array.prototype.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 {}
 *            v вычитаемый массив
 * @param {Boolean}
 *            m в случае если тру, то возвращается только индекс базового
 *            массива
 * @return {Array} разницу массивов
 */
Array.prototype.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} Выделенные элементы
 */
Array.prototype.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;
}
/**
 * Функция переключает класс hide - то есть переключает видимость элемента
 * Нетрудно понять, что в стиля должен быть прописан стиль .hide { display:
 * none; }
 */
Element.prototype.toggle = function() {
	if (this.hasClass('hide')) {
		this.removeClass('hide');
	} else {
		this.addClass('hide');
	}
}
Element.prototype.show = function() {
	if (this.hasClass('hide')) {
		this.removeClass('hide');
	}
}
/**
 * @description Скрывает элемент (добавляет класс hide)
 */
Element.prototype.hide = function() {
	if (!this.hasClass('hide')) {
		this.addClass('hide');
	}
}
/**
 * Функция подключения зависимостей
 */
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);
}
/**
 * Функция переключает элементу значение указанного аттрибута
 * 
 * @param {String}
 *            attr атрибут, с которым работаем
 * @param {Array}
 *            values Значения атрибута, которые нужно менять
 */
Element.prototype.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 элемент формы, либо его идентфикатор
 */
function reset_frm(frm) {
	var control_elements = $(frm).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 = '';
		}
	}
}

/**
 * Коды клавиш, печатающих цифры
 */
var number_key_codes = [48, 57].range().extend([96, 105].range()).extend([8, 9,
		13, 17, 18, 37, 39, 46, 116]);

/**
 * Функция, запрещающая вводить в текстовое поле все, кроме цифр
 * 
 * @param {Element}
 *            elm ссылка на элемент, либо дентификатор элемента, в которого
 *            нужно вводить только цифры
 */
function only_numbers(elm) {
	$(elm).addEvent('keydown', function(e) {
				var event = new Event(e);
				if (!number_key_codes.contains(event.code) && !event.meta) {
					event.stop();
				}
			});
}

/**
 * Проверяем, является ли значение поля числом с плавающей запятой
 * 
 * @param {String|Element}
 *            elm ссылка на элемент, либо дентификатор элемента, в котором стоит
 *            проверить значение
 * @return {Boolean} правда, если значение поля - число в плавающей запятой;
 *         ложь - в обратном случае
 */
function isFloat(elm) {
	if (/^[-+]?[0-9]+(\.[0-9]+)?$/.test($(elm).value.trim())) {
		return true;
	}
	return false;
}

/**
 * Фукнция-транслитератор
 * 
 * @param {String}
 *            string строка, которую нужно транслитирировать
 * @return {String}
 */
function transliterate(string) {
	string = string.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;
}

/**
 * @description Активирует и деактивирует все сабмиты
 * 
 * @param {Boolean}
 *            pos Активировать все сабмиты или деактивировать
 */
function disableSubmits(pos) {
	$each($$('input[type=submit]'), function(subm) {
				if (pos) {
					subm.disabled = true;
				} else {
					subm.disabled = false;
				}
			});

}

/**
 * Автоматическая валидация формы С сервера приходит JSON и переменная
 * validate_forms. Если validate_forms == true, то происходит следующее. По
 * загрузке DOM'a перехватываются все кнопки submit. Далее находится тег form,
 * внутри которого стоит каждая из кнопок и считывается айдишник этой формы
 * (если он есть). Затем мы смотрим, есть ли такой айдишник в JSON и делаем
 * проверку.
 */
window.addEvent('domready', function() {
			if (typeof validate_forms != 'undefined' && validate_forms) {
				if (typeof validation_data != "undefined"
						&& typeof validation_data == 'object'
						&& typeof FormValidator != "undefined") {
					for (var frm in validation_data) {
						FormValidator.set(frm, validation_data[frm], true);
					}
				}

				var forms = $$('form');
				$each(forms, function(frm) {
							var frm_id = frm.getProperty('id');
							if (typeof validation_data[frm_id] != 'undefined') {
								frm.addEvent('submit', function(e) {
											disableSubmits(true);
											if (!FormValidator.validate(frm_id)) {
												new Event(e).stop();
												disableSubmits(false);
											}
										});
							}
						});
			}
		});

window.addEvent('unload', function() {
			disableSubmits(false);
		});