
ViewPort = new Class({

    // Default Options.
    options: {
        outerDiv: 'viewport_outer',
        innerDiv: 'viewport',
        panelClass: 'viewport_panel',
        linkOuter_id: 'viewport_tabs',
        linkClass: 'panellink',
	messageDiv:'viewport_message',
        currentLinkClass: 'current',
        currentPanelClass: 'currentpanel',
        transitionDirection: 'horizontal',
        scrollDuration: 1000,
        transitionCurve: 'Expo',
        transitionEasing: 'easeInOut',
        curveStrength: 1,
        fadeBetweenTransitions: false,
        immediateTransition: false,
        autoScroll: false,
        refreshRate: 10000,
        startPanel: 1,
	callbackFunction:false,
	pausedMessage:'Paused',
        useConsole: false,
        tabLink:false
    },
    panels: Array(),
    initialize: function(options){
    
        // Set the Options.
        this.setOptions(options);
        
        try {
        
            ViewPort.outer = $(this.options.outerDiv);
            if (!ViewPort.outer) {
                throw ("Unable to find Outer - Please check the Element exists and its Id is named in the Options.");
                return false;
            }
            
            // Get the Container, Panels and Tabs as Class properties..
            ViewPort.inner = $(this.options.innerDiv);
            if (!ViewPort.inner) {
                throw ("Unable to find Inner - Please check the Element exists and its Id is named in the Options.");
                return false;
            }
            ViewPort.inner.setStyle('opacity', 0);
            
            ViewPort.panels = $$('#' + this.options.innerDiv + ' .' + this.options.panelClass);
            if (!ViewPort.panels || ViewPort.panels.length < 1) {
                throw ("Unable to find Panels - Please check at least one Element exists and the Class is named in the Options.");
                return false;
            }
            ViewPort.number_of_panels = ViewPort.panels.length;
            
            ViewPort.tabs = $$('#' + this.options.linkOuter_id + ' .' + this.options.linkClass);
            if (!ViewPort.tabs || ViewPort.tabs.length < 1) {
                throw ("Unable to find Panel Tabs - Please check at least one Element exists and the Class is named in the Options.");
                return false;
            }
            ViewPort.number_of_tabs = ViewPort.tabs.length;
			
			if(this.options.hideTabs) {
				$(this.options.linkOuter_id).setStyle('display','none');
			}
            
            if (ViewPort.number_of_panels !== ViewPort.number_of_tabs) {
                throw ("Number of Panels does not match Number of Tabs - Please check the Markup.");
                return false;
            }
            
            if (this.options.transitionDirection == 'vertical') {
                ViewPort.affectCssAttribute = 'margin-top';
                ViewPort.camelAffectCssAttribute = 'marginTop';
                ViewPort.dimensionFlag = 'height';
            }
            else {
                ViewPort.affectCssAttribute = 'margin-left';
                ViewPort.camelAffectCssAttribute = 'marginLeft';
                ViewPort.dimensionFlag = 'width';
            }
            
            // Get the Width of the 1st Panel.
            ViewPort.paneldimension = this.getPanelDimension();
            if (!ViewPort.paneldimension) {
                throw ("Unable to get Panel Dimensions - Please check the Markup.");
                return false;
            }
            
            // Get Start position.
            ViewPort.panelposition = this.getCurrentPosition();
            if (!ViewPort.panelposition == false) {
                throw ("Unable to get Panel Position - Please check the Markup.");
                return false;
            }
            
            // Set Start Position as our Margin.
            ViewPort.startmargin = ViewPort.panelposition;
            
            // Loop thru our Panels.
            ViewPort.panels.each(function(panelEl, i){
                // For each Panel we will set a few things as Properties.
                // Work out each Panels offset by using its index as a modifiier.
                // Remember this needs to be a minus figure as we are using margin-left.
                var ppos = -((ViewPort.startmargin + ViewPort.paneldimension) * i);
                // Set as Prop.
                panelEl.pos = ppos;
                // Set Index as Prop.
                panelEl.index = i;
                
                // Get the corresponding Tab.
                var ta = ViewPort.tabs[i];
                // Add the activeTab and showPanel Methods.
		if(this.options.tabLink == false) {
			ta.addEvent("click", this.resetTabs.bindWithEvent(this, panelEl));
			ta.addEvent("click", this.showPanel.bindWithEvent(this, panelEl));
					ta.addEvent("click", function() {
						ta.blur();
					});
		}                

                // Set the Tab as a property of the Panel.
                panelEl.tab = ta;
                
            }, this);
            // End panel Loop.
			
            // If set in the Options, start a periodical effect.
            if (this.options.autoScroll) {
				var ref = this;
                ViewPort.interval = this.beginPeriodical();
                ViewPort.outer.addEvent("mouseleave", this.beginPeriodical.bindWithEvent(this));
				ViewPort.outer.addEvent("mouseleave", function() {
					if (ref.options.messageDiv && $(ref.options.messageDiv)) {
						$(ref.options.messageDiv).setHTML("");
						$(ref.options.messageDiv).setStyle('display', 'none');
					}
				});
                ViewPort.outer.addEvent("mouseenter", this.pausePeriodical.bindWithEvent(this));
				ViewPort.outer.addEvent("mouseenter", function() {
					if(ref.options.messageDiv && $(ref.options.messageDiv)) {
						$(ref.options.messageDiv).setHTML(ref.options.pausedMessage);
						$(ref.options.messageDiv).setStyle('display','block');
					}
				});
            }

			if (this.options.messageDiv && $(this.options.messageDiv)) {
				$(this.options.messageDiv).setStyle('display', 'none');
			}
            
            // Set Start Panel.
            var sp = (this.options.startPanel - 1);
            if (sp < 0) {
                sp = 0;
            }
            
            ViewPort.current_panel = ViewPort.panels[sp].id;
            ViewPort.next_panel = false;
            
            this.resetTabs();
            this.showPanel(true, ViewPort.panels[sp]);
            
            
        } 
        catch (err) {
            if (this.options.useConsole) {
                alert(err);
            }
        }
        
    },
    resetTabs: function(){
        // Loop thru all Tabs and remove the 'current' css class.
        ViewPort.tabs.each(function(linkEl){
            var l = linkEl.getFirst();
            l.removeClass(this.options.currentLinkClass);
        }, this);
    },
    activeTab: function(){
    
        try {
            this.resetTabs();
            var targ = $(ViewPort.current_panel.tab).getFirst();
            
            // Swap for morph.
            if (targ.addClass(this.options.currentLinkClass)) {
                return true;
            }
            else {
                return false;
            }
        } 
        catch (err) {
            if (this.options.useConsole) {
                alert(err);
            }
            return false;
        }
    },
    showPanel: function(event, panel){
    
        try {
        
            if (event) {
                if ($type(event) == 'object') {
                    event = new Event(event).stop();
                }
            }
            
            var re = this;
            // When we Initialised the Class we looped the Panels and set their offset as a Property.
            var newposition = panel.pos;
            
            // Update properties to the new position.
            ViewPort.panelposition = newposition;
            ViewPort.current_panel = panel;
            
            var myDuration = this.options.scrollDuration;
            var myTransition = this.options.transitionCurve;
            var myEasing = this.options.transitionEasing;
            var curveStrength = this.options.curveStrength;
            
            var tran = new Fx.Transition(Fx.Transitions[myTransition], curveStrength);
            
            var slider = new Fx.Style(ViewPort.inner, ViewPort.affectCssAttribute, {
                duration: myDuration,
                transition: tran[myEasing]
            });
           
            this.activeTab();
 
            // Change the Panel.
            if (this.options.fadeBetweenTransitions) {
            
                // If set this will fade the panel to zero opacity, then change position before fading to 100% opacity.
                // The actual Slide is not visible.
                
                if (this.options.immediateTransition) {
                    ViewPort.inner.setStyle('opacity', 1);
                    slider.set(newposition);
					if (re.options.callbackFunction) {
						re.options.callbackFunction.attempt();
					}
                    // return re.activeTab();
                }
                else {
                
                    var fade = new Fx.Style(ViewPort.inner, 'opacity', {
                        duration: myDuration
                    });
                    
                    fade.start(0).chain(function(){
                        slider.set(newposition);
                        fade.start(1).chain(function(){
							if (re.options.callbackFunction) {
								re.options.callbackFunction.attempt();
							}
                            // return re.activeTab();
                        });
                    });
                    
                }
                
                return false;
                
            }
            else {
            
                // This is the default effect - horizontal or vertical slide.
                ViewPort.inner.setStyle('opacity', 1);
                slider.start(newposition).chain(function(){
					if (re.options.callbackFunction) {
						re.options.callbackFunction.attempt();
					}
                    // return re.activeTab();
                });
                
            }
            
            // We should have returned true by now...		
            return false;
        } 
        catch (err) {
            if (this.options.useConsole) {
                alert(err);
            }
            return false;
        }
    },
    getCurrentPosition: function(panel){
    
        // This is called on Class initialisation to get the start position.
        // ViewPort.camelAffectCssAttribute is either 'width' or 'height'. 
        
        var pos = false;
        if (!panel) {
            pos = (ViewPort.inner) ? ViewPort.inner.getStyle(ViewPort.camelAffectCssAttribute).toInt() : 0;
        }
        else {
            pos = $(panel) ? $(panel).getStyle(ViewPort.camelAffectCssAttribute).toInt() : 0;
        }
        return pos;
    },
    getPanelDimension: function(){
    
        // This is called on Class initialisation to get the panel width or height. 
        // The script assumes all panels are the same width or height.
        
        if ((ViewPort.panels) && (ViewPort.panels.length > 0) && (!ViewPort.panelDimension)) {
            ViewPort.panelDimension = ViewPort.panels[0].getStyle(ViewPort.dimensionFlag).toInt();
        }
        return (ViewPort.panelDimension) ? ViewPort.panelDimension : 0;
    },
    periodicScroll: function(ref){
        var nextIndex = $(ViewPort.current_panel).index + 1;
        var len = ViewPort.panels.length;
        
        if (nextIndex == len) { nextIndex = 0; }
        
        var nextPanel = ViewPort.panels[nextIndex];
        if (nextPanel && nextPanel.tab) {
            this.resetTabs();
            this.showPanel(true, nextPanel);
        }
        return true;
    },
    beginPeriodical: function(){
    
        this.resetPeriodical();
        var myRefreshRate = this.options.refreshRate;
        ViewPort.interval = this.periodicScroll.periodical(myRefreshRate, this);
        
        return ViewPort.interval;
    },
    pausePeriodical: function(){
        return this.resetPeriodical();
    },
    resetPeriodical: function(){
        return $clear(ViewPort.interval);
    }
});

// Extend the ViewPort Class with the Options Class.  
ViewPort.implement(new Options());

