var CustomInput = {
	create: function (element, type, options) {
		var element = $(element);
		var tag = element.tagName.toLowerCase();
		switch (tag) {
			case 'input': {
				switch (type) {
					case 'validated':
						return new CustomInput.ValidatedInput (element, options);
					case 'color':
						return new CustomInput.ColorInput (element, options);
					case 'font':
						return new CustomInput.FontInput (element, options);
					case 'date':
						return new CustomInput.DateInput (element, options);
					case 'time':
						break;
					case 'spin':
						return new CustomInput.SpinInput (element, options);
					default: return false;
				}
				break;
			}
			case 'select': {
				break;
			}
			case 'textarea': {
				break;
			}
			default: return false;
		}
	}
};

CustomInput.ValidatedInput = Class.create ({
	initialize: function (element, options) {
		this.options = {errorCSSClass: 'validated_input_error', validateFunction: null, validateRegEx: null, canBeEmpty: true};
		this.element = element;
		Object.extend (this.options, options);
		this.oldErrorState = false;
		this._onValueChange = this.onValueChange.bindAsEventListener(this);
		Event.observe(element, "change", this._onValueChange);
		Event.observe(element, "keyup", this._onValueChange);
		Event.observe(element, "blur", this._onValueChange);
		Event.observe(element, "focus", this._onValueChange);
	},
	onValueChange: function () {
		var value = this.element.value;
		var error = false;
		if (this.options.canBeEmpty && value == '') {
			error = false;
		} else {
			if (this.options.validateRegEx)
				if (!this.options.validateRegEx.test(value)) error = true;
			if (this.options.validateFunction)
				if (!this.options.validateFunction(value)) error = true;
		}

		if (error != this.oldErrorState) {
			if (error)
				this.showError();
			else
				this.showOK();
			this.oldErrorState = error;
		}
	},
	showOK: function () {
		this.element.removeClassName (this.options.errorCSSClass);
	},
	showError: function () {
		this.element.addClassName (this.options.errorCSSClass);
	}
});
CustomInput.SpinInput = Class.create(TemplatedElement, {
	initialize: function (element, options) {
		this.options = {minValue:0,maxValue:10,defaultValue:0,step:1};
		Object.extend(this.options, options || {});
		this._buildFromTemplate('spin_input_template');
		this.input = element;
		this.input.parentNode.insertBefore(this.element, this.input);
		this.inputHolder.innerHTML = this.btnUp.innerHTML = this.btnDown.innerHTML = '';
		this.inputHolder.appendChild (this.input);
		Event.observe(this.input, "change", this.onValueChange.bindAsEventListener(this));
		Event.observe(this.input, "mousewheel", this.onMouseWheel.bindAsEventListener(this));
	},
	fitValue: function (val) {
		if (val < this.options.minValue) return this.options.minValue;
		if (val > this.options.maxValue) return this.options.maxValue;
		return val;
	},
	onClickUp: function () {
		this.setValue (this.getValue() + this.options.step);
	},
	onClickDown: function () {
		this.setValue (this.getValue() - this.options.step);
	},
	onValueChange: function () {
		this.setValue (this.getValue());
	},
	setValue: function (val) {
		val = this.fitValue(val);
		this.input.value = val;
		if (this.onChange) this.onChange(val);
		return val;
	},
	getValue: function () {
		var v = parseInt(this.input.value);
		if (isNaN(v)) return this.options.defaultValue;
		return v;
	},
	onMouseWheel: function (event) {
		var d = event.getWheelDelta();
		if (d > 0) this.onClickUp();
		if (d < 0) this.onClickDown();
		event.stop();
	}
});
if (typeof TDatePicker != 'undefined') CustomInput.DateInput = TDatePicker;
if (typeof TColorPicker != 'undefined') CustomInput.ColorInput = TColorPicker;
if (typeof TFontPicker !=' undefined') CustomInput.FontInput = TFontPicker;


$ST = function (element) {
	element = $(element);
	if (element.getSelected && element.setSelected) return element;
	Object.extend (element, {
		getSelected: function () {
			if (element.selectedIndex >= 0 && element.selectedIndex < element.options.length)
				return element.options[element.selectedIndex].value;
			else
				return '';
		},
		setSelected: function (value) {
			for (var i = 0, n = element.options.length; i < n; i ++)
				if (element.options[i].value == value) {
					element.selectedIndex = i
					return i;
				}
			return false;
		}
	});
	return element;
	// TODO : add easy options creation via method addOption (name, value, selected)
}
// element is actually array of the options
$RB = function (element) {
	if (element.getSelected && element.setSelected) return element;
	Object.extend (element, {
		getSelected: function () {
			for (var i = 0, n = element.length; i < n; i ++)
				if (element[i].checked) return element[i].value;
			return null;
		},
		setSelected: function (value) {
			for (var i = 0, n = element.length; i < n; i ++)
				if (element[i].value == value) {
					element[i].checked = true;
					return i;
				}
		},
		setOnChangeHandler: function (handler) {
			for (var i = 0, n = element.length; i < n; i ++)
				element[i].onclick = handler;
		}
	});
	return element;
}