;(function($) {

	$.widget("ui.stringSelect", $.extend({
	
	    get: function() {
	        return this.value
	    },
	
	
		setPendingValue: function(value) {
			this.pendingValue = value
		},
	
	    set: function(value) {
			//console.trace()
			//console.log("%d set assign %s", this.getId(), value)
	
			var oldValue = this.value
		    if (typeof(this.getData) == 'function') {
		        if (!this.getData('options').data[value]) {
					// if value does not exist => we just take first option
				    for(var prop in this.getData('options').data) {
		                value = prop
		                break
		            }
		        }
		    }
	        this.value = value
			this.renderValue();
	
		    // trigger on filtered value
			this.element.triggerHandler("select", [value, oldValue])
	    },
	
		renderValue: function() {
			this.element.html(this.getOptionLabel(this.value))
		},
	
	    loadOptions: function(req) {
	       // console.log("%d loadOptions",this.getId())
	
			this.ajaxController.sendRequest(req)
	    },
	
		onLoaded: function(data){
			//console.log("%d loadOptions loader callback: %o", this.getId(), data)
	
			if (data) {
				this._setData('options', data)
	
				this.lazyRefreshOptionsDone = false
				//self.refreshOptions()
				this.set(this.pendingValue)
				this.element.triggerHandler("ready")
			}
	
			this.pendingValue = null
		},
	
	
		lazyRefreshOptions: function() {
			this.refreshOptions();
			this.lazyRefreshOptionsDone = true
		},
	
		getOptionLabel: function(prop) {
		    if (typeof(this.getData) == 'function') {
		      return this.getData('options').data[prop]
		    }
		    return undefined;
		},
	
	    refreshOptions: function() {
	
	        var o = this.element[0]
	
	        var opts = this.getData('options')
	
	        //console.log("%d refreshOptions: %o", this.getId(), opts)
	
	        //this.mousePointerOverOption = false
	
	    	$('#' + o.id + '_list').remove();
	
	        var html = ['<div class="select_list_wrap hide" id="' + o.id + '_list"> \
	            <ul class="select_list">'];
	
			var i=0, c=0;
			if (!opts.best_idx) opts.best_idx = 999
	        for(var prop in opts.data) {
	
				if (i==opts.best_idx) {
					html.push('<li class="' + (c++%2 == 0 ? 'even' : 'odd') + '"><a href="javascript:void(0)" id="'+this.getId()+'-left">...остальные...</a></li>')
				}
	
	            html.push(
					'<li value="' + prop + '" class="' + (c++%2 == 0 ? 'even' : 'odd') + '"' + (i>=opts.best_idx ? ' style="display:none"':'')+'>' + this.getOptionLabel(prop) + '</li>'
					)
				i++
			}
	
	        html.push('</ul></div>');
	
	
	        $(html.join('')).appendTo('body');
	
	    	var $container = this.$container = $(document.getElementById(o.id + '_list'))
	
	
			var self = this
	
	
	        $('li', $container).each(function(k, o) {
				if (!o.getAttribute('value')) return
				$(o).click(function(e) {
					self.select(e.tagName === undefined ? this : e)
				})
				.hover(
					function() { $('li.over', $container).removeClass("over"); $(this).addClass("over"); },
					function() { $(this).removeClass("over"); }
				)
			})
	
			this.leftLink = $('#'+this.getId()+'-left')
	
			this.leftLink.parent().click(
				function(e) {
					self.showLeft()
					self.leftLink.blur()
					$('ul', $container).stop().scrollTo(this, 100)
				}
			)
	
	
	
			// check if number is among OTHERs, show others if yes it is among others
			var i=0;
			for(var prop in this.getData('options').data) {
				if (prop == this.value) {
					if (i>this.getData('options').best_idx) {
						this.showLeft()
					}
					break
				}
				i++
			}
	
	    },
	
	
		showLeft: function() {
			if (this.leftShown) return
	
			o = this.leftLink.parent()
			o.nextAll().each(function (k,v) {
				v.style.display = '';
			})
			this.leftLink.html('остальные:')
			//o.addClass('stringSelect-left-pressed')
	
			this.leftShown = true
		},
	
	    open: function() {
			if(this.$container.isShow())
				return;
	
			var self = this
			$('li', this.$container).each(
				function(i, li) {
				if(li.value == self.value)
					self.selectedIndex = i;
				}
			);
	
			this.moveSelect(0);
			//fixIE.show();
	
			floatWidget.activePush(this)
			this.$container.css("left", this.element.offset().left).css("top", this.element.offset().top + this.element.outerHeight()).show();
	
			this.scrollToOver();
	    },
	
	    select: function(e) {
	        // e must be LI element
	
			//this.mousePointerOverOption = false;
			this.close();
	
			if (e.value != this.value) {
				this.set(e.value)
			}
	
	    },
	
		scrollToOver: function() {
			/* scroll must be called on UL , not on div */
			$list = $('ul', this.$container)
			var over = $('li.over', $list)
			if(over.length > 0) {
				$list.stop().scrollTo(over.get(0), 100)
			}
		},
	
		moveSelect: function (step)	{
			var $lis = $('li', this.$container);
			if (!$lis.length) return;
	
			this.selectedIndex += step;
	
			if (this.selectedIndex < 0)
				this.selectedIndex = 0;
			else if (this.selectedIndex >= $lis.size())
				this.selectedIndex = $lis.length - 1;
	
			$lis.removeClass("over");
			$($lis[this.selectedIndex]).addClass("over");
	    },
	
	
	    close: function() {
			this.$container.hide();
			floatWidget.activePop(this)
	    },
	    
	    _init: function() {
	    	this.init.apply(this, arguments);
	    },
	    
	    init: function() {
			$.widget.prototype._init.apply(this,arguments)
			this.ajaxController = new AjaxController(this, this._getData('sendRequestPrefix'), this._getData('sendRequestPostfix'))
			this.selectedIndex = 0
			this.is_focus = false
			this.lazyInited = false
	
			var self = this
	
			this.element.click(
			    function(){
					this.blur()
					if (!self.lazyRefreshOptionsDone) self.lazyRefreshOptions()
	
					if(self.$container.isShow())
						self.close();
					else
						self.open();
	
			    })
			.keydown(function(e) {
					if (!self.lazyRefreshOptionsDone) self.lazyRefreshOptions()
	
	                switch(e.keyCode) {
	                    case 38: // up
	                            e.preventDefault();
	                            self.moveSelect(-1);
	                            self.scrollToOver();
	                            break;
	                    case 40: // down
	                            e.preventDefault();
	                            self.moveSelect(1);
	                            self.scrollToOver();
	                            break;
	                    case 9:  // tab
	                    case 13: // return
	                            var $over = $('li.over', self.$container);
	                            if ($over.length > 0) {
	                                //mousePointerOverOption = true
	                                self.select($over.get(0));
	                                e.preventDefault();
	                            }
	                            break;
	                    default:
	                            self.selectedIndex = -1;
	                            break;
	                }
		    })
	
			if (this._getData('options')) {
	            //this.refreshOptions()
	            this.set(this._getData('selectedValue'));
	        }
	
			this.setHiders(true)
	
	    },
	
	
		hasPendingValue: function() {
			return !!this.pendingValue
		}
	
	
	}, floatWidgetMixin, stringLoadingWidgetMixin))
	
	
	$.widget("ui.RoSiSelect", $.extend({}, $.ui.stringSelect.prototype, {
		renderValue: function() {
			var label = this._getData('options').data[this.value]
	
			// cut long lines
			if (label.match('ребен'))
				label = label.replace(/ взр\S+/,' взр.')
	
			this.element.html(label)
		}
	}))
	
	
	
	$.widget("ui.CoSelect", $.extend({}, $.ui.stringSelect.prototype, {
		getOptionLabel: function(prop) {
	
			var label = this._getData('options').data[prop]
	
			var main_regions = this._getData('options').main_regions
			var main_region = main_regions && main_regions[prop]
	
			if (main_region) {
				var name = (prop == 74) ? 'Канары' : main_region.name
				label = name+' ('+label+')'
			}
			
			return label
		},
	
		renderValue: function() {
			
			this.element.html(this._getData('options').data[this.value])
		}
	}))
	
	$.extend($.ui.RoSiSelect, {
		getter: 'hasPendingValue get getOptionLabel'
	});
	$.extend($.ui.CoSelect, {
		getter: 'hasPendingValue get getOptionLabel'
	});
	$.extend($.ui.stringSelect, {
		getter: 'hasPendingValue get getOptionLabel'
	});
	
	//$.ui.RoSiSelect.getter = $.ui.CoSelect.getter = $.ui.stringSelect.getter = "hasPendingValue";
})(jQuery);