var List = new Class({
    Implements: [Options, Events],
    options: {
        element: null,
        hover: true,
        select: true
    },
    element: null,
    selected: null,
    items: null,
    initialize: function(options) {
        this.setOptions(options);
        if (!this.options.element) {
            this.element = new Element('ul');
        } else {
            this.element = $(this.options.element);
        }
        this.items = [];
    },
    
    toElement: function() {
        return this.element;
    },
    
    add: function(item) {
        var li = new Element('li');
        if (this.options.hover) {
            li.addEvents({
                mouseenter: function() {
                    if (!this.hasClass('selected')) {
                        this.addClass('hover');
                    }
                },
                mouseleave: function() {
                    this.removeClass('hover');
                }
            });
        }
        if (this.options.select) {
            li.addEvent('click', (function(evt) {
                this.select(item);
            }).bind(this));
        }
        li.adopt(item.toElement());
        this.element.adopt(li);
        if (item.options.selected) {
            this.select(item, item.options.addSilently || false);
        }
        item.addEvent('deselect', this.deselect.bind(this, item));
        this.items.push(item);
        this.fireEvent('add', item);
    },
    
    remove: function(item) {
        if (this.items.contains(item)) {
            this.items.erase(item);
            var li = item.toElement().getParent('li');
            if (li) {
                li.removeEvents('click');
                if (this.selected == item) {
                    item.deselect();
                    this.selected = null;
                }
                var that = this;
                li.setStyle('overflow','hidden');
                li.tween('height', 0).get('tween').chain(function(){
                    item.dispose();
                    li.dispose();
                    that.fireEvent('remove', item);
                    if (!that.selected && that.items.length > 0) {
                        //that.select(that.items[0]);
                    }
                })
            }
        }
    },
    
    deselect: function(item, silently) {
        if (item && this.selected == item) {
            item.deselect(silently);
            var li = item.toElement().getParent('li');
            li.removeClass('selected');
            this.selected = null;
            this.fireEvent('deselect', [item, silently || false]);
            if (this.options.select) {
                (function(){
                    li.addEvent('click', (function(){this.select(item);}).bind(this));
                }).delay(1,this);
            }
        }
    },
    
    select: function(item, silently) {
        if (this.selected == item) {
            return;
        }
        this.deselect(this.selected);
        this.selected = item;
        if (item) {
            var li = item.toElement().getParent('li');
            li.removeEvents('click');
            li.removeClass('hover');
            li.addClass('selected');
            item.select(silently || false);
            this.fireEvent('select', [item, silently || false]);
        }
    },
    
    empty: function() {
        this.items.each(function(item) {
            item.dispose();
        });
        this.element.empty();
        this.items = [];
        this.selected = null;
    }
});

var Item = new Class({
    Family: 'Item',
    Implements: [Options, Events],
    options: {
        element: null
    },
    initialize: function(options) {
        this.setOptions(options);
        if (this.options.element) {
            this.element = $(this.options.element);
        } else {
            this.element = this.createElement();
        }
    },
    toElement: function() {
        return this.element;
    },
    createElement: function() {
        return new Element('div');
    },
    dispose: function() {
        this.removeEvents();
        this.element.dispose();
    },
    select: function(silently) {},
    deselect: function(silently) {}
});
