
if(!CBI) var CBI = {};

CBI.Navigation = Class.create({
    initialize: function(element, options){
        this.options = Object.extend({
            url: '/navigation.php'
        }, options || {});
        this.element = $(element);
        this.data = [];
        
        new Ajax.Request(this.options.url, {
            method:'get', 
            onSuccess: function(response){
                this.data = response.responseJSON;
                this.menu = new CBI.Navigation.Menu(this.data);
                this.element.update(this.menu);
            }.bind(this)
        });
    }
});

CBI.Navigation.Menu = Class.create({
    initialize: function(data){
        this.data = data;
        this.items = this.data.map(function(item){
            return new CBI.Navigation.Item(item, this);
        }.bind(this));
        this.element = new Element('ul', {'class':'menu'})
            .insertCollection(this.items)
            .observe('mouseenter', function(){ $(document).fire('cbi:navigation:shown'); })
            .observe('mouseleave', function(){ $(document).fire('cbi:navigation:hidden'); });
    }, 
    
    toElement: function(){
        return this.element;
    }, 
    
    item_is_shown: function(){
        return this.items.any(function(item){
            return item.submenu.element.visible();
        });
    }
});

CBI.Navigation.Item = Class.create({
    initialize: function(data, menu){
        this.data = data;
        this.menu = menu;
        
        this.submenu = new CBI.Navigation.SubMenu(this.data.items);
        this.element = new Element('li', {'class': this.data.class_name })
            .insert(new Element('span').update(this.data.title))
            .insert(this.submenu);
        
        if(this.data.url){
            this.element.observe('click', function(){
                window.location = '/' + this.data.url;
            }.bind(this));
        }
        
        this.enter_listener = this.element.on('mouseenter', this.enter.bind(this));
        this.leave_listener = this.element.on('mouseleave', this.leave.bind(this));
    }, 
    
    toElement: function(){
        return this.element;
    }, 
    
    enter: function(){
        if(this.menu.item_is_shown()){
            // Prevent items waiting to be shown from queueing up.
            $(document).stopObserving('cbi:navigation:item_hidden');
            
            // Show the next nav item after the previous menu has fully collapsed.
            var observer = function(){
                this.submenu.show();
                $(document).stopObserving('cbi:navigation:item_hidden', observer);
            }.bind(this);
            $(document).observe('cbi:navigation:item_hidden', observer);
        }
        else this.submenu.show();
    }, 
    
    leave: function(){
        this.submenu.hide();
    }
});

CBI.Navigation.SubMenu = Class.create({
    initialize: function(data){
        this.data = data;
        this.is_hovered = false;
        this.items = this.data.map(function(item, i){
            return new CBI.Navigation.SubItem(item, i);
        });
        this.element = new Element('ul', {'class':'submenu'})
            .hide()
            .insertCollection(this.items)
            .observe('mouseenter', function(){ this.is_hovered = true; }.bind(this))
            .observe('mouseleave', function(){ this.is_hovered = false; }.bind(this));
    }, 
    
    toElement: function(){
        return this.element;
    }, 
    
    show: function(){
        if(this.items.length == 0)
            return;
        
        this.element.show();
        var timeout = 0;
        this.items.each(function(item){
            $(document).fire('cbi:navigation:item_shown');
            setTimeout(function(){ item.show(); }, timeout);
            timeout += 40;
        });
    }, 
    
    hide: function(){
        if(this.is_hovered || this.items.length == 0)
            return;
        
        new Effect.Fade(this.element, {
            duration: .2, 
            afterFinish: function(){
                this.items.invoke('reset');
                $(document).fire('cbi:navigation:item_hidden');
            }.bind(this)
        });
    }
});

CBI.Navigation.SubItem = Class.create({
    initialize: function(data, index){
        this.data = data;
        
        this.image = new Element('img', { src: this.data.image });
        this.animate_image = this.image.clone();
        this.button = new Element('a', { href: '/' + this.data.url })
            .insertCollection([
                new Element('div').insertCollection([this.animate_image, this.image]), 
                new Element('span').update(this.data.title)
            ]);
        this.element = new Element('li')
            .setStyle({'z-index': 100 - index })
            .update(this.button)
            .observe('mouseenter', this.enter.bind(this))
            .observe('mouseleave', this.leave.bind(this));
        
        if(this.data.items && this.data.items.length){
            this.submenu = new CBI.Navigation.SubSubMenu(this.data.items);
            this.element.insert(this.submenu);
        }
        
        this.reset();
    }, 
    
    toElement: function(){
        return this.element;
    }, 
    
    enter: function(){
        this.image.hide(); 
        this.effect = new Effect.Move(this.animate_image, {
            x: -80, 
            duration: .9, 
            transision: Effect.Transitions.Quad.easeOut
        });
        if(this.submenu)
            this.submenu.show();
    }, 
    
    leave: function(){
        if(this.effect)
            this.effect.cancel();
        
        this.image.appear({
            duration: .3, 
            afterFinish: function(){
                this.animate_image.setStyle({ top: 0, left: 0 });
            }.bind(this)
        });
        if(this.submenu)
            this.submenu.hide();
    }, 
    
    show: function(callback){
        this.element.appear({
            duration: 0.4, 
            // transition: Effect.Transitions.Quart.easeOut, 
            queue: { scope: this.element.identify(), position:'end'}, 
            afterFinish: callback
        });
        // new Effect.Move(this.element, {
        //     y: this.element.getHeight(), 
        //     mode:'absolute', 
        //     duration: 0.4, 
        //     transition: Effect.Transitions.Quart.easeOut, 
        //     queue: { scope: this.element.identify(), position:'end'}, 
        //     afterFinish: callback
        // });
    }, 
    
    reset: function(){
        // this.element.setStyle({ top: px(-20) });
        this.element.hide();
        this.leave();
    }
});

CBI.Navigation.SubSubMenu = Class.create({
    initialize: function(data){
        this.data = data;
        this.items = this.data.map(function(item){
            return new CBI.Navigation.SubSubItem(item);
        });
        this.element = new Element('ul', {'class':'subsubmenu'})
            .hide()
            .insertCollection(this.items);
    }, 
    
    toElement: function(){
        return this.element;
    }, 
    
    show: function(){
        new Effect.Appear(this.element, {
            duration: .2
        });
    }, 
    
    hide: function(){
        new Effect.Fade(this.element, {
            duration: .2
        });
    }
});

CBI.Navigation.SubSubItem = Class.create({
    initialize: function(data){
        this.data = data;
        
        this.button = new Element('a', { href: '/' + this.data.url })
            .update(this.data.title);
        this.element = new Element('li').update(this.button);
    }, 
    
    toElement: function(){
        return this.element;
    }
});




