Site.Controllers.Rollover = Class.create
(
    Site.Base,
    {
        initialize: function($super, element, triggerSelector, rolloverSelector, options)
        {
            $super();
            
            this.element = element;
            
            this.triggerSelector = triggerSelector;
            this.rolloverSelector = rolloverSelector;
            
            this.setOptions
            (
                options,
                {
                    durationRolloverShow: 0,
                    //delayRolloverShow: 0.1,
                    //delayRolloverHide: 0.2,
                    delayRolloverShow: 0.0,
                    delayRolloverHide: 0.0,
                    triggerKey: "trigger",
                    rolloverKey: "rollover"
                }
            );
            
            this.addObservers("triggerOnMouseOver", "triggerOnMouseOut", "rolloverOnMouseOver", "rolloverOnMouseOut");
            
            this.showTimeouts = {};
            this.hideTimeouts = {};

            this.triggers = this.element.select(this.triggerSelector);
            this.rollovers = this.element.select(this.rolloverSelector);
            
            this.hideRollovers();
            
            this._setupEvents();
        },
        
        stick: function()
        {
            // prevent this rollover from closing
        },
        
        hideRollovers: function()
        {
            // hide the rollovers
            this.rollovers.invoke("hide");
                
            this.activeRollover = null;
        },
        
        showRollover: function(rollover)
        {   
            this.activeRollover = rollover;
            
            this.hideIdleRollovers();
            
            if (this.options.durationRolloverShow > 0)
            {
                new Effect.Appear(rollover, { duration: this.options.durationRolloverShow } );
            }
            else
            {
                rollover.show();
            }
        },

        hideRollover: function(rollover)
        {   
            rollover.hide();
            this.activeRollover = null;
        },
        
        hideIdleRollovers: function()
        {
            this.rollovers.each
            (
                function(rollover)
                {
                    if (rollover != this.activeRollover)
                        rollover.hide();
                },
                this
            ); 
        },
        
        triggerOnMouseOver: function(event)
        {
            var trigger = Event.element(event).matchUp(this.triggerSelector);

            if (rollover = this._getRolloverForElement(trigger))
            {
                // register this timeout - uses late binding to pass the correct rollover through as a param
                this.showTimeouts[rollover.id] = window.setTimeout(this.showRollover.bind(this, rollover), this.options.delayRolloverShow * 1000);
            }
        },
    
        triggerOnMouseOut: function(event)
        {
            var trigger = Event.element(event).matchUp(this.triggerSelector);

            if (rollover = this._getRolloverForElement(trigger))
            {
                // clear any timeouts for this rollover to prevent it being shown if the user skims the mouse across 
                if (this.showTimeouts[rollover.id])
                {
                    window.clearTimeout(this.showTimeouts[rollover.id]);
                }
            }
            
            rollover = null;
        },
                
        rolloverOnMouseOver: function(event)
        {
            var element = Event.element(event);
            
            var rollover = element.matchUp(this.rolloverSelector);
            
            if (rollover)
            {
                // clear any hide timeouts
                
                if (this.hideAllTimeout)
                    window.clearTimeout(this.hideAllTimeout);
                
                if (this.hideTimeouts[rollover.id])
                    window.clearTimeout(this.hideTimeouts[rollover.id]);
            }
        },

        rolloverOnMouseOut: function(event)
        {
            var element = Event.element(event);
            
            // find the rollover div
            var rollover = element.matchUp(this.rolloverSelector);
            
            if (rollover)            
            {
                this.hideTimeouts[rollover.id] = window.setTimeout(this.hideRollover.bind(this, rollover), this.options.delayRolloverHide * 1000);
            }
        },
        
        _getRolloverForElement: function(trigger)
        {
            if (trigger && trigger.id)
            {
                // find the rollover associated with this element, by replacing the element key with the rollover key
                // this is how their ids must differ
                return $(trigger.id.replace(this.options.triggerKey, this.options.rolloverKey));
            }
        },
        
        _setupEvents: function()
        {
            // setup the rollover events for elements in the results grid
            this.triggers.each
            (
                function(trigger)
                {
                    addEvent(trigger, 'mouseover', this.observers.triggerOnMouseOver);
                    addEvent(trigger, 'mouseout', this.observers.triggerOnMouseOut);
                },
                this
            ); 

            this.rollovers.each
            (
                function(rollover)
                {
                    addEvent(rollover, 'mouseover', this.observers.rolloverOnMouseOver);
                    addEvent(rollover, 'mouseout', this.observers.rolloverOnMouseOut);
                },
                this
            ); 
        },
        
        destroy: function()
        {
            this.triggers.each
            (
                function(trigger)
                {
                    removeEvent(trigger, 'mouseover', this.observers.triggerOnMouseOver);
                    removeEvent(trigger, 'mouseout', this.observers.triggerOnMouseOut);
                },
                this
            ); 

            this.rollovers.each
            (
                function(rollover)
                {
                    removeEvent(rollover, 'mouseover', this.observers.rolloverOnMouseOver);
                    removeEvent(rollover, 'mouseout', this.observers.rolloverOnMouseOut);
                },
                this
            ); 
            
        }
        
    }
);
