var dependent_select_fields = [];

function dependent_select_fields_init() {
    $A(dependent_select_fields).each(function(x) {x.init()});
    $A(dependent_select_fields).each(function(x) {
	    if (!x.options.opt_set) x.update()});}

if (window.addEventListener)
    window.addEventListener('load', dependent_select_fields_init, false);
else if (window.attachEvent)
    window.attachEvent('onload', dependent_select_fields_init);

DependentSelectFieldManager = Class.create()

DependentSelectFieldManager.prototype.initialize = 
function(field_id, options, depends) {
    this.id = field_id;
    this.field = $(field_id);
    this.spinner = $(field_id + '_spinner');
    this.options = Object.extend({}, options || {});
    this.depends = depends;
    this.wait = false;
    this.updating = false;
    this.re_update = false;
    this.dependet = [];
    dependent_select_fields[
	dependent_select_fields.length] = this;
};

DependentSelectFieldManager.prototype.init = function() {
    $A(this.depends).each(function(x) {
	    $(x['field_id']).observe('change',
		this.on_change.bind(this));
	    var m = Try.these(
		    function() {return eval(x['field_id'] + '_manager')});
	    if (m) m.dependet[m.dependet.length] = this;
	    }.bind(this));
}

DependentSelectFieldManager.prototype.on_change = function(event) {
    if (this.updating)
	this.re_update = true;
    else
	this.update();
}

DependentSelectFieldManager.prototype.update = function() {
    var is_busy = function(field_id) {
	var m = Try.these(
		function() {return eval(field_id + '_manager')});
	return m && (m.updating || m.wait);
    }

    var params = {};

    for (var i = 0; i < this.depends.length; i++) {
	var d = this.depends[i];
	if (is_busy(d['field_id'])) {
	    this.wait = true;
	    return;
	}
	var f = $(d['field_id']);
	var v = f.value;
	for (var j = 0; v == '' && j < d['fallback_fields'].length; j++) {
	    var fd = d['fallback_fields'][j];
	    if (is_busy(fd)) {
		this.wait = true;
		return;
	    }
	    v = $(fd).value;
	}
	if (v == '') {
	    if (d['if_empty'] == null)
		continue;
	    v = d['if_empty'];
	}
	params[d['feeder_param']] = v;
    }

    this.wait = false;
    this.updating = true;
    this.spinner.className += ' active';
    
    var request_options = {method: 'post',
                           parameters: $H(params).toQueryString(),
                           onSuccess: this.requestOk.bind(this),
                           onFailure: this.requestFailed.bind(this)};
    
    new Ajax.Request(
	    this.options.controller, request_options);
}

DependentSelectFieldManager.prototype.requestOk = function(request) {
    if (this.re_update) {
	this.re_update = false;
	this.update();
	return;
    }

    var results;
    eval('results = ' + request.responseText);
    
    if (typeof(results) != 'object' &&
        typeof(results.options) != 'object') {
         alert('There was a problem processing the request.');
    }
    
    var value = this.field.value;
    this.field.options.length = 0;
    $A(results.options).each(function(opt) {
	o = new Option(opt[1], opt[0]);
	if (opt[0] == value) o.selected = true;
        this.field.options.add(o);
    }.bind(this));
    this.field.value = value;
    
    this.spinner.className = this.spinner.className.replace(
            /\s*\bactive\b/, '');
    this.updating = false;
    $A(this.dependet).each(function(x) {x.update();});
}

DependentSelectFieldManager.prototype.requestFailed = function(request) {
    this.spinner.className = this.spinner.className.replace(
            /\s*\bactive\b/, '');    
    this.updating = false;
    alert('There was a problem with the request (code: ' + 
          request.status + ' "' + request.statusText + '")');
}

