/**
 * @author timharwood
 */

var DestroyableItem = new Class({

    Implements: [Events, Options],
    
    options: {
        id: 'DestroyableItem-' + new Date().getTime() + "-" + Math.random(),
        debug: true
    },
    
    initialize: function(options){
        this.setOptions(options);
    },
    
    doDestroy: function(){

        this.fireEvent('destroy', {
            type: 'destroy',
            target: this
        });
        this.removeEvents();
        try{
            this.destroy();
        }catch(e){
            
        }
    }
});

var AbstractCollectionItem = new Class({
    
    Extends: DestroyableItem,
    Implements: [Events, Options],
    
    options: {
        id: 'SelectableCollectionItem-' + new Date().getTime() + "-" + Math.random(),
        content: null,
        debug: true
    },
    
    initialize: function(options){
        this.parent(options);
    },
    
    getContent: function(){
        return this.options.content;
    },
    
    setContent: function(obj){
        if (this.options.content != obj) {
            this.options.content = obj;
            this.fireEvent('contentUpdate', {
                type: 'contentUpdate',
                target: this
            });
        }
    }
});

var SelectableCollectionItem = new Class({

    Extends: AbstractCollectionItem,
    Implements: [Events, Options],
    
    options: {
        id: 'SelectableCollectionItem-' + new Date().getTime() + "-" + Math.random(),
        content: null,
        selected: false,
        debug: false
    },
    
    initialize: function(options){
        this.parent(options);
    },
    
    getSelected: function(){
        return this.options.selected;
    },
    
    setSelected: function(state){
        if (this.options.selected != state) {
            this.options.selected = state;
            var evt = (state) ? "select" : "deselect";
            this.fireEvent(evt, {
                type: evt,
                target: this
            });
        }
    }
    
});


var AbstractCollection = new Class({

    Extends: SelectableCollectionItem,
    Implements: [Events, Options],
    
    options: {
        id: 'AbstractCollection-' + new Date().getTime() + "-" + Math.random(),
        items: [],
        currentIndex: -1,
        loop: true,
        debug: true
    },
    
    onItemSelect: null,
    onItemDeselect: null,
    
    initialize: function(options){
        this.parent(options);
        if (this.options.items.length > 0) {
            this.options.items.each(this.attachItemListener.bind(this));
        }
        this.onItemSelect = function(e){
            this.itemSelect(e);
        }.bind(this);
        
        this.onItemDeselect = function(e){
            this.itemDeselect(e)
        }.bind(this);
        
    },
    
    attachItemListener: function(item){
        item.addEvent('select', this.onItemSelect);
        item.addEvent('deselect', this.onItemDeselect);
    },
    
    removeItemListener: function(item){
        item.removeEvent('select', this.onItemSelect);
        item.removeEvent('deselect', this.onItemDeselect);
    },
    
    getItems: function(){
        return this.options.items;
    },
    
    removeAllItems: function(destroy){
        this.options.items.each(function(el, ix){
            this.removeItem(el,destroy);
        }.bind(this));
        
        var f = this.fireEvent('itemsRemoved', {
            type: 'itemsRemoved',
            target: this
        });
        
        this.options.items=[];
    },
    
    randomiseItems: function(){
        this.options.items.sort(function(){
            return (Math.round(Math.random()) - 0.5);
        });
    },
    
    addItem: function(item, force){
        if (force || !this.options.items.contains(item)) {
            this.attachItemListener(item);
            this.options.items.push(item);
        }
        
        var f = this.fireEvent('itemAdded', {
            type: 'itemAdded',
            target: this,
            item:item
        });
    },
    
    removeItem: function(item, destroy){
        if (this.options.items.contains(item)) {
            this.removeItemListener(item);
            this.options.items.erase(item);
        }
        
        var f = this.fireEvent('itemRemoved', {
            type: 'itemAdded',
            target: this,
            item:item
        });
        
        if (destroy) {
            item.doDestroy();
        }
    },
    
    removeItemAt: function(index){
        if (this.options.items.length > index) {
            this.removeItem(this.options.items[index]);
        }
    },
    
    getCurrentItem: function(){
        if (this.options.items.length > 0 && this.options.items[this.options.currentIndex]) {
            return this.options.items[this.options.currentIndex];
        }
        else {
            return null;
        }
    },
    
    getCurrentIndex: function(){
        return this.options.currentIndex;
    },
    
    setCurrentIndex: function(index){
        if (this.options.items.length > index && this.options.currentIndex != index) {
        
            var itm = this.getCurrentItem();
            
            if (itm) {
                itm.setSelected(false);
            }
            
            this.options.currentIndex = index;
            
            itm = this.getCurrentItem();
            
            if (itm) {
                itm.setSelected(true);
            }
            
            var f = this.fireEvent('onIndexChange', {
                type: 'onIndexChange',
                target: this,
                index:this.options.currentIndex
            });
            
        }
    },
    
    setCurrentItem: function(item){
    
        var index = this.options.items.indexOf(item);
        if (index > -1) {
            this.setCurrentIndex(index);
        }
    },
    
    nextItem: function(){
        var newIndex = this.options.currentIndex + 1;
        if (newIndex > this.options.items.length - 1) {
            newIndex = (this.options.loop) ? 0 : this.options.items.length - 1;
            var f = this.fireEvent('onPassEnd', {
                type: 'onPassEnd',
                target: this,
                index:this.options.currentIndex,
                newIndex:newIndex
            });
        }
        this.setCurrentIndex(newIndex);
    },
    
    prevItem: function(){
        var newIndex = this.options.currentIndex - 1;
        if (newIndex < 0) {
            newIndex = (this.options.loop) ? this.options.items.length - 1 : 0;
            var f = this.fireEvent('onPassBeginning', {
                type: 'onPassBeginning',
                target: this,
                index:this.options.currentIndex,
                newIndex:newIndex
            });
        }
        this.setCurrentIndex(newIndex);
    },
    
    hasNext:function() {
      return ( (this.options.items.length>1) && (this.options.loop || (this.options.currentIndex<this.options.items.length - 1) ));
    },
    
    hasPrev:function() {
      return ( (this.options.items.length>1) && (this.options.loop || (this.options.currentIndex>0) ));
    },
    
    itemSelect: function(e){
        this.setCurrentItem(e.target);
    },
    
    itemDeselect: function(e){
    
    }
    
});

var TimerplayCollection = new Class({

    Extends: AbstractCollection,
    Implements: [Events, Options],
    
    options: {
        id: 'TimerplayCollection-' + new Date().getTime() + "-" + Math.random(),
        items: [],
        currentIndex: -1,
        loop: true,
        autoplay: false,
        delay: 7000,
        debug: false
    },
    
    timer: null,
    
    initialize: function(options){
        this.parent(options);
        if (this.options.autoplay) 
            this.play();
    },
    
    play: function(){
        if (this.timer) 
            clearInterval(this.timer);
        this.timer = setInterval(this.nextItem.bind(this), this.options.delay);
        this.nextItem();
    },
    
    stop: function(){
        if (this.timer) 
            clearInterval(this.timer);
    }
    
});

