Treelink = Class.create({
    selectors : new Array(),
    resourceUrl : null,
    loading : 0,
    maxLevel : 0,
    searchLevel : 0,
    
    initialize : function(resourceUrl, node, searchLevel) {
        this.resourceUrl = resourceUrl;
        this.searchLevel = searchLevel;
        $('treelink-reset').observe('click', this.resetClick.bind(this));
        if (node) {
            this.loadName();
            $('treelink-search').disabled = false;
        } else {
            $$('.treelink-select select').each(function(select) {
                this.selectors.push(select);
                this.maxLevel++;
                select.observe('change', this.onSelectorChange.bind(this));
            }.bind(this));
            this.reloadSelectors();
        }
    },
    
    reloadSelectors : function(target) {
        var updateElm = false;
        var resetElm = false;
        if (!target) {
            updateElm = true;
        }
        this.selectors.each(function (selector) {
            var selectorLevel = this.getSelectorLevel(selector);
            if (resetElm) {
                this.clearSelect(selector);
                this.hideSelect(selectorLevel);
            } else if (updateElm) {
                var url = this.buildUrl(selectorLevel);
                if (!url) {
                    return;
                }
                this.loadResource(selector, url);
                updateElm = false;
                resetElm = true;
            } else {
                this.showSelect(selectorLevel);
            }
            if (selectorLevel == target) {
                updateElm = true;
            }
        }.bind(this));
    },
    
    onSelectorChange : function(event) {
        this.selectorChange(event.element());
    },
    
    selectorChange : function(elm) {
        var currentLevel = this.getSelectorLevel(elm);
        $('treelink-node').value = this.getSelectedNode(elm);
        this.reloadSelectors(this.getSelectorLevel(elm));
        $('treelink-search').disabled = !($F(elm) != '(title)' && currentLevel == this.maxLevel);
    },
    
    getSelector : function(level) {
        var result = null;
        this.selectors.each(function (selector) {
            if (this.getSelectorLevel(selector) == level) {
                result = selector;
            }
        }.bind(this));
        return result;
    },
    
    getSelectorLevel : function(elm) {
        return parseInt(elm.id.replace('treelink-select-level', ''));
    },
    
    getSelectedNode : function(elm) {
        var level = this.getSelectorLevel(elm);
        var val = $F(elm);
        if (val == '(title)') {
            return 0;
        }
        return val;
    },
    
    buildUrl : function(level) {
        var url = this.resourceUrl + 'nodes/';
        if (level > 1) {
            var val = this.getSelectedNode(this.getSelector(level - 1));
        } else {
            var val = 0;
        }
        return this.resourceUrl + 'nodes/node/' + val + '/level/' + level + '/';
    },

    loadResource : function(elm, url) {
        elm.disable();
        ++this.loading;
        this.toggleSpinner();
        new Ajax.Request(url, {
            method: 'get',
            requestHeaders: { Accept : 'application/json' },
            onSuccess: function(response) {
                this.updateSelect(elm, response.responseText.evalJSON());
                --this.loading;
                this.toggleSpinner();
            }.bind(this)
        });
    },
    
    loadName : function(id) {
        var url = this.resourceUrl + 'name';
        new Ajax.Request(url, {
            method: 'get',
            onSuccess: function(response) {
                if (response.responseText) {
                    $('treelink-status').update(response.responseText);
                    $$('.treelink-selector').first().addClassName('node-selected');
                }
            }.bind(this)
        });
    },
    
    toggleSpinner : function() {
        if (this.loading == 0) {
            $('treelink-spinner').hide();
        } else {
            $('treelink-spinner').show();                
        }
    },
    
    clearSelect : function(elm) {
        Element.select(elm, '.dynamic').each(Element.remove);
        elm.disable();
    },
    
    updateSelect : function(elm, data) {
        var currentLevel = this.getSelectorLevel(elm);
        this.clearSelect(elm);
        if (data.length > 0) {
            data.each(function(item) {
                elm.insert('<option class="dynamic" value="' + item.id + '">' + item.value + '</option>');
            });
            elm.enable();
            if (elm.options.length == 2) {
                elm.selectedIndex = 1;
                this.selectorChange(elm);
            } else {
                elm.selectedIndex = 0;
            }
            this.showSelect(currentLevel);
        } else {
            this.forceHideSelect(currentLevel);
        }
        $('treelink-search').disabled = !(data.length <= 1 || (this.searchLevel != 0 && currentLevel > this.searchLevel));
    },
    
    resetClick : function(event) {
        location.href = this.resourceUrl + 'reset/';
    },
    
    showSelect : function(level) {
        $('treelink-select-container-level' + level).addClassName('auto-display');
        $('treelink-select-container-level' + level).removeClassName('auto-no-display');
    },
    
    hideSelect : function(level) {
        $('treelink-select-container-level' + level).removeClassName('auto-display');
    },

    forceHideSelect : function(level) {
        $('treelink-select-container-level' + level).addClassName('auto-no-display');
        $('treelink-select-container-level' + level).removeClassName('auto-display');
    },
    
    fireEvent : function(element, event) {
        if (document.createEventObject) {
            // dispatch for IE
            var evt = document.createEventObject();
            return element.fireEvent('on'+event,evt)
        } else {
            // dispatch for firefox + others
            var evt = document.createEvent("HTMLEvents");
            evt.initEvent(event, true, true);
            return !element.dispatchEvent(evt);
        }
    }
});
