/** ==================================================
 * Wrap Class para a tag select
 * Implementa métodos rotineiros como adicionar, remover, procurar, etc
================================================== */
function Select(id) {
	this.select = $(id)
}

Select.prototype.getValue = function() {
	return this.select.value
//	return this.select.options[this.select.selectedIndex].value
}

Select.prototype.getText = function() {
	return this.select.options[this.select.selectedIndex].text
}

/**
 * recebe uma string que contém o html de um select com seus options,
 * e cria um objeto option apartir deste html
 */
Select.factoryFromSelectHtml = function(str) {
	var foo = $c('div')
	foo.innerHTML = str
	return new Select(foo.firstChild)
}

/**
 * recebe uma string que contém o html dos options de um select,
 * mas sem o select. Adiciona um select padrão e passa para a função acima
 */
Select.factoryFromOptionHtml = function(str) {
	var foo = $c('div')
	return Select.factoryFromSelectHtml("<select>" + str + "</select>")
}

/**
 * Adiciona um option à lista com as propriedades definidas no info
 */
Select.prototype.add = function (info) {
	var data = typeof(info) == 'string'  ? {'text':info} : info
	var option = $c("option", data)
	this.select.options.add(option)
	return this.select.length - 1;
}

/**
 * Limpa o select, removendo todos os options
 */
Select.prototype.clear = function () {
	for(var i = 0; i < this.select.length; i++) {
		this.removeIndex(i--)
	}
}

/**
 * Remove o option no índice index
*/
Select.prototype.removeIndex = function(index) {
	this.select.remove(index)
}

/**
 * Procura um único option (o primeiro encontrado)
*/
Select.prototype.find = function(cmp) {

	var f = Select.getCmpFunction(cmp)
	var opt = null

	for(var i = 0; i < this.select.length; i++) {
		if( f(opt = this.select.options[i]) )
			return opt
	}

	return null
}

/**
 * Retorna todas as ocorrências
*/
Select.prototype.findAll = function(cmp) {

	var f = Select.getCmpFunction(cmp)
	var opt = null
	var foundeds = []

	for(var i = 0; i < this.select.length; i++) {
		if( f(opt = this.select.options[i]) )
			foundeds.push(opt)
	}

	return foundeds
}

/**
 * Remove todos elementos encontrados
 */
Select.prototype.remove = function(cmp) {

	var f = Select.getCmpFunction(cmp)

	for(var i = 0; i < this.select.length; i++) {
		if( f(this.select.options[i]) )
			this.removeIndex(i--)
	}
}

/**
 * substitui o select interno por uma copia do select do parâmetro
 */
Select.prototype.copy = function(select) {
	var src = select.select == undefined ? $(select) : select.select
	var copy = src.cloneNode(true)
	this.select.parentNode.replaceChild(copy, this.select)
	this.select = copy
}

/**
 * Não Funciona no IE
 */
Select.prototype.copyOptions = function(select) {
	var src = select.select == undefined ? $(select) : select.select
	var copy = src.cloneNode(true)
	this.clear()
	for(var i = 0; i < copy.options.length; i++) {
		this.add(copy.options[i])
		//this.select.options.add(copy.options[i])
		//this.select.options[i] = copy.options[i]
	}
}

/**
 * Não Funciona
 * @var options Array de options, acessado por selec.options
 */
Select.prototype.replaceOptions = function(options) {
	var opts = []
	this.clear()
	for(var i = 0; i < options.length; i++) {
		opts.push(options[i])
	}

	for(var j = 0; j < opts.length; j++) {
		this.select.options[j] = opts[j]
	}
	//this.select.options.selectedIndex = 0
}

/**
 * @access private
 * factory que retorna uma função de comparação baseado no parâmetro
*/
Select.getCmpFunction = function(cmp) {

	// retorna a própria função
	if(cmp instanceof Function) {
		return cmp
	}

	// faz match na propriedade text
	else if (cmp instanceof RegExp) {
		return function(option) {
			return option.text.match(cmp)
		}
	}

	// string exata caseInsensitive em text
	else if (typeof(cmp) == 'string') {
		return function(option) {
			return option.text.toLowerCase() == new String(cmp).toLowerCase()
		}
	}

	// Compara o número com a String value
	else {
		return function(option) {
			return option.value.toLowerCase() == new String(cmp).toLowerCase()
		}
	}

}


/** ==================================================
 * Class AjaxSelectBind
 * ================================================== */
function SelectBindAjax(src, dest, url) {
	this.selectBind = new SelectBind(src, dest)
	this.id = this.selectBind.src.select.getAttribute('name')
	var parent = this

	this.onResult = function(req, timer) {
		var sNew = false
		var value = req.responseText
		if(value != "") {
			sNew = Select.factoryFromSelectHtml(value)
		}
		parent.selectBind.update(sNew)
	}

	this.selectBind.trigger = function(value) {
		var name = parent.id
		var params = {}
		params[name] = value
		AJAX.get(url, parent.onResult, params)
	}
}

/** ==================================================
 *  Class SelectBind
 * ================================================== */
function SelectBind(src, dest, trigger) {

	this.src = new Select(src)
	this.dest = new Select(dest)
	var parent = this
	if(trigger) this.trigger = trigger

	this.change = function(evt) {
		parent.disable()
		parent.trigger(parent.src.getValue())
	}

	$addEvent(this.src.select, 'change', this.change)
}

SelectBind.prototype.enable = function() {
	this.src.select.disabled = false
	this.dest.select.disabled = false
	this.src.select.style.cursor = "default"
	this.dest.select.style.cursor = "default"
}

SelectBind.prototype.disable = function() {
	this.src.select.style.cursor = "wait"
	this.dest.select.style.cursor = "wait"
	this.src.select.disabled = true
	this.dest.select.disabled = true
}

SelectBind.prototype.trigger = function(value) {
	var sNew = false
	if(value > 0) {
		sNew = Select.factoryFromSelectHtml("<select><option>"+value+"</option></select>")
	}
	this.update(sNew)
}

SelectBind.prototype.update = function(sNew) {
	if(typeof(sNew) == 'object') {
		this.dest.copy(sNew)
	}
	this.enable()
	this.dest.select.focus()
}