$(function(){
	$.fn.extend({
		combo: function(config){
			this.each(comboInit);

			function comboInit(){
				$('combo-select').hide();
				var srcSelect = $(this);
				srcSelect.wrap('<div class="combo"></div>');

				var select = {
					'id': srcSelect[0].id,
					'title': srcSelect[0].title,
					'combo': srcSelect.parent(),
					'width': srcSelect.outerWidth(),
					'defaultsign': srcSelect.attr('defaultsign'),
					'defaultunit': srcSelect.attr('defaultunit'),
					'units': srcSelect.attr('units'),
					'unit': srcSelect.attr('defaultunit'),
					'hiddenInput': config['hiddenInput'],
					'allownegative': srcSelect.attr('allownegative') == 'false' ? false : true
				}

				var decodedURI;
				try {
					decodedURI = decodeURI(config['hiddenInput'].val());
				} catch (e) {
					decodedURI = config['hiddenInput'].val();
				}

				select['value'] = config['hiddenInput'].length ? decodedURI : '';
				select['options'] = [];

				for (var i = 0; i < srcSelect[0].options.length; i++){
					select['options'].push({
						value: srcSelect[0].options[i].value,
						text: srcSelect[0].options[i].text
					});
				}
				select['inputContainer'] = $('<div class="combo-input"></div>').appendTo(select['combo']);
				select['input'] = $('<input autocomplete="off" type="text"/>')
					.attr('maxlength', 15)
					.attr('title', select['title'])
					.width(select['width'] - 4)
					.appendTo(select['inputContainer']);

				if (select['id']) select['input'].attr('id', select['id']);
				if (select['name']) select['input'].attr('name', select['name']);

				select['input'].tooltip({
					track: true,
					showURL: false,
					extraClass: 'white'
				});

				srcSelect.remove();

				select['input'].val(select['value']);

				select['input'].bind('click focus', function(e){
					if (!select['selectContainer']){
						comboShow();
					}
				});

				select['input'].bind('keydown', selectKeydown);
				select['input'].bind('keypress', selectKeypress);
				select['input'].bind('blur', selectChange);
				select['input'].bind('change', selectChange);

				$(window).bind('resize scroll', comboHide);

				function comboContainer(){
					select['selectContainer'] = $('<ul class="combo-select"></ul>').appendTo('body');
					select['selectContainer'].bind('mousedown', comboClick);

					$(select['selectContainer']).mouseover(function(e){
						$(this).find('li').removeClass('selected');
						if (e.target.tagName.toLowerCase() == 'li'){
							$(e.target).addClass('selected');
						};
					});

					for (var i = 0; i < select['options'].length; i++){
						var option = $('<li></li>').attr('val', select['options'][i].value).html(select['options'][i].text).appendTo(select['selectContainer']);
					}

					$('<span class="clear"></span>').appendTo(select['selectContainer']);

					if ($(select['selectContainer']).outerWidth() < select['input'].outerWidth()){
						$(select['selectContainer']).width(select['input'].outerWidth() - 2);
						$(select['selectContainer']).find('li').width(select['input'].outerWidth() - 6);
					}
 				}

				function comboClick(e){
					if (!select['selectContainer']) return;

					if (e.target == select['input'][0]){
						return;
					} else if ($(e.target).closest('ul.combo-select')[0] == select['selectContainer'][0]){
						e.preventDefault();
						e.stopPropagation();
						select['input'].val($(e.target).attr('val'));
						return comboHide(true);
					}

				  comboHide();
				}

				function getSelectedIndex(e){
					if (!select['selectContainer']) return;
					var selectedIndex;
					$(select['selectContainer']).find('li').each(function(i, el){
						if ($(el).hasClass('selected')){
							selectedIndex = i;
						}
					});				

				  return selectedIndex;
				}

				function comboSelect(index){
					if (!select['selectContainer']) return;
					$(select['selectContainer']).find('li').removeClass('selected');
					if (index >= 0){
						$(select['selectContainer']).find('li').eq(index).addClass('selected');
					}
				}

				function comboCheckSelection(){
					if (!select['selectContainer']) return;

					for (var i = 0; i < select['options'].length; i++){
						var a = $(select['selectContainer']).find('li').eq(i);
						if (select['input'].val().toLowerCase() == select['options'][i].value.toLowerCase()){
							a.addClass('selected');
						} else {
							a.removeClass('selected');
						}
					}
				}

				function comboShow(){
					comboContainer();
						$(select['selectContainer']).css({
							top: select['input'].offset().top + select['input'].outerHeight(),
							left: select['input'].offset().left
						}).show()//.bgIframe();
					comboCheckSelection();
				}

				function comboMarkInvalid(select, valid){
					if (valid){
						select['input'].removeClass('form-invalid');
					} else {
						select['input'].addClass('form-invalid');
					}
				}

				function comboValidate(){
					var errtype;
					var valid = true;
					var regexInterval = /^([\-]?[.\d]+)(?:[-]{1}([\-]?[.\d]+))$/; // -1, 1, 10.321-20.5, -10-20, -20--30
					var val = select['input'].val().replace(/\s/g, '');
					var sign = '';
					var defaultsign = select['defaultsign'];
					var unit = select['defaultunit'];
					var units = (select['units'] && eval(select['units']) instanceof Array) ? eval(select['units']) : '';
					if (units.length){
						$(units).each(function(i, el){
							var currentunit = units[i].replace(/\s/g, '');
							if (val.indexOf(currentunit) > -1){
								if (currentunit = val.substring(val.length - currentunit.length)){
									unit = units[i];
								} else {
//									if (!errtype) errtype = 'единица измерения (' + currentunit + ') в неправильном месте строки';
									valid = false;
								}
							}
						});
					} else if (unit && val.indexOf(unit.replace(/\s/g, '')) > -1 && unit.replace(/\s/g, '') != val.substring(val.length - unit.replace(/\s/g, '').length)){
//						if (!errtype) errtype = 'единица измерения в неправильном месте строки';
						valid = false;
					}

					if (!val){
						select['input'].val( '' );
						comboMarkInvalid(select, true);
						return true;
					}

					if (unit) val = val.replace(unit.replace(/\s/g, ''), '');

					if (val.indexOf('-') != 0 && val.indexOf('<') != 0	&& val.indexOf('>') != 0 && !val.substring(0, 1).match(/\d/)){
//						if (!errtype) errtype = 'строка начинается НЕ с минуса/знака больше/знака меньше/цифры';
						valid = false;
					}

					if (val.indexOf('<') == 0 || val.indexOf('>') == 0){
						sign = val.substring(0, 1);						
						val = val.substring(1);
					}

					if (sign && val.indexOf('-') > 1){
//						if (!errtype) errtype = 'присутствует знак больше или меньше и указан промежуток';
						valid = false;
					}

					if (val == parseFloat(val) || val.match(regexInterval)){
						if (parseFloat(val) < 0 && select['allownegative'] === false){
//							errtype = 'не может быть отрицательным';
							valid = false;
						}
						if (val == parseFloat(val) && !sign){
							sign = defaultsign;
						} else if (val.match(regexInterval)){

							var first = parseFloat(val.match(regexInterval)[1]);
							var second = parseFloat(val.match(regexInterval)[2]);

							val = first + ' - ' + second;

							if (first > second){
//								if (!errtype) errtype = 'первое число в промежутке (' + first + ') больше второго (' + second + ')';
								valid = false;
							} else if (first == second){
								val = (sign ? sign : defaultsign) + first;
							} else if (sign){
//								if (!errtype) errtype = 'присутствует знак "' + sign + '" и указан промежуток';
								valid = false;
							}
						}
					} else {
//						if (!errtype) errtype = val + ' - не число и не промежуток';
						valid = false;
					}

					valid ? comboMarkInvalid(select, true) : comboMarkInvalid(select, false);

					if (valid){
						select['input'].val( sign + val + (unit ? unit : '') );
					} else {
//						alert(errtype);
					}

					return valid;
				}

				function comboHide(submit){
					var valid = comboValidate();
					if (submit !== true && !select['selectContainer']) return;
					comboCheckSelection();
					if (select['selectContainer']){
						select['selectContainer'].remove()
						delete select['selectContainer'];
					}
					select['value'] = select['input'].val();
					if (valid){
						config['onchange'].call(select);
						if (submit === true){
							config['onenter'].call(select);
						}
					}
				}

				function selectKeydown(e){
					var hidden = !select['selectContainer'];
					var index = getSelectedIndex();
					if (e.keyCode == 38){ // up
						e.preventDefault();
						e.stopPropagation();
						if (index > 0){
							comboSelect(index - 1);
						} else {
							comboHide();
						}
					} else if (e.keyCode == 40){ // down
						e.preventDefault();
						e.stopPropagation();
						if (index + 1 != select['options'].length){
							comboSelect(index >= 0 ? index + 1 : 0);
						}
						if (hidden){
							comboShow();
//						comboSelect(-1);
						}
					} else if (e.keyCode == 13){
						e.preventDefault();
						e.stopPropagation();
						select['input'].val($(select['selectContainer']).find('li').eq(index).attr('val'));
						comboHide(true);
					} else {
						setTimeout(function(){
							comboCheckSelection(e);
						}, 0);
					}
				}

				function selectKeypress(e){
					var index = getSelectedIndex();
					if (e.keyCode == 13){
						comboSelect(index);
						e.preventDefault();
						e.stopPropagation();
						select['input'].val($(select['selectContainer']).find('li').eq(index).attr('val'));
						comboHide(true);
					} 
				}

				function selectChange(e, submit){
					if (e.keyCode == 13) return;
					e.preventDefault();
					e.stopPropagation();
					comboHide(submit);
				}
			}
		}
	});
});
