(function() {

	SL.ui.Slider = Class.create(SL.Component, {
		init : function() {

			this.config.setDefault('range_min', 0);
			this.config.setDefault('range_max', 100);

			this.left = this.e.down('.left');
			this.grip = this.e.down('.grip');
			this.right = this.e.down('.right');

			this.input = $(this.config.get('input_id'));

			this.cb = this.config.ensureHash('cb');

			this.draggable = new SL.dnd.Draggable(this.grip, {
				orientation : 'horizontal',
				spacer_width : 0,
				cb : {
					moved : this.moved.bind(this)
				}
			});

			this.e.observe('click', this.onClick.bind(this));

			if (this.input && this.input.value) {
				var rangeMin = this.config.get('range_min');
				var rangeMax = this.config.get('range_max');

				var pct = (this.input.value - rangeMin) / (rangeMax - rangeMin) * 100.0;
				this.setPCT(pct, true);
			} else if (this.config.get('init_value') != undefined) {
				var rangeMin = this.config.get('range_min');
				var rangeMax = this.config.get('range_max');

				var pct = (this.config.get('init_value') - rangeMin) / (rangeMax - rangeMin) * 100.0;
				this.setPCT(pct, true);
			}
		},

		setCB : function(cb) {
			this.cb = cb;
		},

		onClick : function(e) {

			var xOffset = e.pageX - this.e.cumulativeOffset().left;

			var gripWidth = this.grip.getWidth();
			var width = this.e.getWidth();

			var pos = xOffset - gripWidth / 2;
			if (pos < 0) {
				pos = 0;
			} else if (pos > (width - gripWidth / 2)) {
				pos = this.e.getWidth() - gripWidth / 2;
			}

			this.grip.setStyle({
				left : pos + 'px'
			});

			this.moved();
		},

		moved : function() {

			var pos = this.grip.positionedOffset().left;
			var gripWidth = this.grip.getWidth();
			var width = this.e.getWidth();

			this.percentage = pos * 100.0 / (width - gripWidth);

			var value = this.getValue();

			if (this.cb.moved) {
				this.cb.moved(this, pos, this.percentage, value);
			}

			if (this.input) {
				this.input.value = value;
			}

			this.sendAsyncUpdate();
		},

		sendAsyncUpdate : function() {

			if (!this.config.get('update_url')) {
				return;
			}

			if (this.asyncUpdate) {
				clearTimeout(this.asyncUpdate);
			}

			var url = this.config.get('update_url');
			url = url.replace("@value@", this.getValue());

			this.asyncUpdate = setTimeout(function() {
				new Ajax.Request(url, {
					method : 'get',
					onSuccess : function(o) {
						eval(o.responseText);
						this.asyncUpdate = undefined;
					}.bind(this)
				});
			}, 250);
		},

		emitMoved : function() {
			if (this.cb.moved) {
				var value = this.getValue();
				var pos = this.grip.positionedOffset().left;
				this.cb.moved(this, pos, this.percentage, value);
			}
		},

		getValue : function() {
			var rangeMin = this.config.get('range_min');
			var rangeMax = this.config.get('range_max');

			return rangeMin + Math.round(((rangeMax - rangeMin) * this.percentage / 100.0));
		},

		setValue : function(value, init) {
			var rangeMin = this.config.get('range_min');
			var rangeMax = this.config.get('range_max');

			var pct = (value - rangeMin) / (rangeMax - rangeMin) * 100.0;
			this.setPCT(pct, init);
		},

		setPCT : function(pct, init) {
			this.percentage = pct;

			var eWidth = this.e.getWidth();
			var gripWidth = this.grip.getWidth();

			if (eWidth <= 0) {
				eWidth = this.config.get('width');
			}

			if (gripWidth <= 0) {
				gripWidth = 5;
			}

			if (pct < 0) {
				pct = 0;
			} else if (pct > 100) {
				pct = 100;
			}

			var pos = Math.round((eWidth - gripWidth) * pct / 100);

			this.grip.setStyle({
				left : pos + 'px'
			});

			var rangeMin = this.config.get('range_min');
			var rangeMax = this.config.get('range_max');

			var value = rangeMin + Math.round(((rangeMax - rangeMin) * this.percentage / 100.0));

			if (this.input) {
				if (this.input.value != value) {
					this.input.value = value;
					if (!init) {
						this.sendAsyncUpdate();
					}
				}
			} else if (!init) {
				this.sendAsyncUpdate();
			}
		},

		getPCT : function() {
			return this.percentage;
		},

		refresh : function() {
			this.setPCT(this.percentage);
		}
	});

	SL.ui.Dropdown = Class.create(SL.Component, {

		init : function() {

			this.config.setDefault('min_width', 50);

			this.input = $(this.config.get('input_id'));
			this.cb = this.config.ensureHash('cb');

			this.label = this.e.down('.' + this.config.get('css') + '_label');
			this.options = this.e.down('.' + this.config.get('css') + '_options');

			this.optionsPanel = new SL.ui.Panel(this.options, {
				attach_id : this.id
			});

			this.label.observe('click', this.optionsPanel.toggle.bind(this.optionsPanel));

			var elements = this.options.childElements();

			for ( var i = 0; i < elements.length; i++) {
				var e = elements[i];
				e.observe('click', this.onItemClicked.bind(this, i));
			}

			this.updateMinWidth();
		},

		setCB : function(cb) {
			this.cb = cb;
		},

		onItemClicked : function(index) {
			var item = this.config.get('data')[index];

			if (this.input) {
				this.input.value = item.id;
			}

			this.label.down().update(item.label);

			if (this.cb.changed) {
				this.cb.changed(this, item.id, item.label);
			}

			if (item.on_select) {
				item.on_select(this, item);
			}

			this.optionsPanel.toggle();

			this.updateMinWidth();
		},

		updateMinWidth : function() {

			if (this.label.getWidth() <= 0) {
				return;
			}

			var lw = this.label.down().getWidth() + 10;
			if (lw <= 10 || lw < this.config.get('min_width')) {
				return;
			}

			if (lw > this.label.getWidth()) {
				this.label.setStyle({
					width : lw + 'px'
				});
			}
		}
	});

})();

