MediaLibraryAutoCompleter = Class.create(Ajax.Autocompleter, {
    startIndicator: function() {
        this.element.addClassName('autocomplete_indicator');
    },

    stopIndicator: function() {
        this.element.removeClassName('autocomplete_indicator');
    },

    onComplete: function(request) {
        var data = request.responseText.evalJSON();
        
        var result = '<ul>';
        for (var i = 0; i < data.results.length; i++) {
            result += '<li>' + data.results[i].text + '</li>';
        }
        result += '</ul>';
        
        this.updateChoices(result);
    }
});

MediaItemAutoCompleter = Class.create(Ajax.Autocompleter, {
    suggestion: '',
    data: null,

    onKeyPress: function(event) {
        if (this.active) {
            switch(event.keyCode) {
                case Event.KEY_TAB:
                case Event.KEY_RETURN:
                    this.selectEntry();
                    Event.stop(event);
                case Event.KEY_ESC:
                    this.hide();
                    this.active = false;
                    Event.stop(event);
                    return;
                case Event.KEY_BACKSPACE:
                case Event.KEY_DELETE:
                case Event.KEY_LEFT:
                case Event.KEY_RIGHT:
                    return;
                case Event.KEY_UP:
                    this.markPrevious();
                    this.render();
                    Event.stop(event);
                    return;
                case Event.KEY_DOWN:
                    this.markNext();
                    this.render();
                    Event.stop(event);
                    return;
            }
        } else {
            if (event.keyCode==Event.KEY_BACKSPACE || event.keyCode==Event.KEY_DELETE || event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) {
                return;
            }
        }

        this.changed = true;
        this.hasFocus = true;

        if (this.observer) {
            clearTimeout(this.observer);
        }
        this.observer = setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
    },

    onClick: function(event) {
        var element = Event.findElement(event, 'A');
        this.tokenBounds = null;
        if (element) {
            if (element.hasClassName('close')) {
                this.hide();
                this.element.focus();
            } else {
                var token = element.innerHTML;
                this.insertToken(token);
                for (var i = 0; i < this.data.length; i++) {
                    if (this.data[i].text == token) {
                        this.data = this.data.without(this.data[i]);
                        break;
                    }
                }
                this.suggestion = token;
                this.doAutoCompletion(this.data);
            }
        } else {
            element = Event.findElement(event, 'INPUT');
            if (element) {
                element = Event.findElement(event, 'LI');
                this.index = element.autocompleteIndex;
                this.selectEntry();
                this.hide();
            } else {
                this.element.focus();
            }
        }
        Event.stop(event);
        return false;
    },

    onBlur: function() {
    },

    insertToken: function(value) {
        var bounds = this.getTokenBounds();
        if (bounds[0] != -1) {
            var newValue = this.element.value.substr(0, bounds[0]);
            var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
            if (whitespace) {
                newValue += whitespace[0];
            }
            this.element.value = newValue
                               + this.suggestion
                               + this.options.separator
                               + value;
        } else {
            this.element.value = value;
        }
        this.oldElementValue = this.element.value;

        this.element.focus();

        if (this.options.afterUpdateElement)
            this.options.afterUpdateElement(this.element, selectedElement);
    },

    updateElement: function(selectedElement) {
        if (this.options.updateElement) {
            this.options.updateElement(selectedElement);
            return;
        }
        var value = '';
        if (this.options.select) {
            var nodes = $(selectedElement).select('.' + this.options.select) || [];
            if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
        } else {
            value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
        }
        this.insertToken(value);
    },

    getUpdatedChoices: function() {
        this.startIndicator();
        var entry = encodeURIComponent(this.options.paramName) + '='
                  + encodeURIComponent(this.element.value);
        this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry;
        if (this.options.defaultParams) {
            this.options.parameters += '&' + this.options.defaultParams;
        }
        new Ajax.Request(this.url, this.options);
    },

    onComplete: function(request) {
        var data = request.responseText.evalJSON();
        this.data = data.results;
        this.suggestion = data.suggestion;
        this.doAutoCompletion(data.results);
        this.doAutoSuggestion(this.suggestion);
    },

    doAutoCompletion: function(data) {
        var result = '<ul>';
        if (data.length > 0) {
            result += '<li>';
            result += '<a href="#" class="close"></a>';
            for (var i = 0; i < data.length; i++) {
                if (i > 0) {
                    result += this.options.separator;
                }
                result += '<a href="#">' + data[i].text + '</a>';
            }
            if (this.options.buttons) {
                result += '<span class="buttons">';
                for (i = 0; i < this.options.buttons.length; i++) {
                    result += '<input type="button" value="' + this.options.buttons[i].title +'" />';
                }
                result += '</span>';
            }
            result += '</li>';
        }
        result += '</ul>';
        
        this.updateChoices(result);
    },

    doAutoSuggestion: function(suggestion) {
        var element = this.element;

        this.tokenBounds = null;
        var tokenBounds = this.getTokenBounds();
        var prefix = element.value.substr(tokenBounds[0], tokenBounds[1]);
        var whitespaceIndex = 0;
        for (var i = 0; i < prefix.length; i++) {
            if (prefix.charAt(i) == ' ') {
                whitespaceIndex++;
            } else {
                break;
            }
        }
        prefix = prefix.substr(whitespaceIndex, prefix.length);
        
        var appendix = '';
        if (!prefix.empty()) {
            if (suggestion.startsWith(prefix)) {
                appendix = suggestion.substr(prefix.length, suggestion.length - 1);
            }
        }
        
        if (!appendix.empty()) {
            var length = element.value.length;
            element.value += appendix;
            this.doSelection(element, length, length + appendix.length);
        }
    },

    doSelection: function(element, start, end) {
        if (element.selectionStart != undefined) { //Gecko
            element.setSelectionRange(start, end);
        } else {  //IE6/7
            selection = element.createTextRange();
            selection.collapse(true);
            selection.moveStart('character', start);
            selection.moveEnd('character', end);
            selection.select();
        }
    }
});
