var sr = new Array();
var st = new Array();
var SlideRotator = Class.create();
var CacheSize = 2;

SlideRotator.prototype = {
   initialize: function(slideGroupId, dynamic, duration, transition, pauseOnMouseFocus, customSlideLayout, direction, slideId){
      this.slideGroupId = slideGroupId;
      this.dynamic = dynamic;
      this.duration = duration;
      this.transition = transition;
      this.pauseOnMouseFocus = pauseOnMouseFocus;
      this.customSlideLayout = customSlideLayout;
      this.lastTransitionTime = (new Date()).getTime();
      this.cachedSlides = new Array();
      this.cacheWasEmpty = false;
      this.lastSlideId = slideId;
      this.upcomingSlideId = -1;
      this.currentRequestId = 1;

      if (parseInt($("dvFrontParent" + slideGroupId).style.zIndex) > parseInt($("dvBackParent" + slideGroupId).style.zIndex)) {
         this.currentSlide = "dvBack" + slideGroupId;
         this.nextSlide = "dvFront" + slideGroupId;
         this.currentSlideParent = "dvBackParent" + slideGroupId;
         this.nextSlideParent = "dvFrontParent" + slideGroupId;       
      } else {
         this.currentSlide = "dvFront" + slideGroupId;
         this.nextSlide = "dvBack" + slideGroupId;
         this.currentSlideParent = "dvFrontParent" + slideGroupId;
         this.nextSlideParent = "dvBackParent" + slideGroupId;        
      }

      this.paused = false;
      this.direction = direction;
      
      if (pauseOnMouseFocus)
      {
         Event.observe("dvContent"+slideGroupId, 'mouseover', this.onMouseOver.bind(this));
         Event.observe("dvContent"+slideGroupId, 'mouseout', this.onMouseOut.bind(this));
      }
                  
      this.flip(1);
      
      //Replace link for Previous and Next Slide Links
      if(this.dynamic)
      {
         if($("GoPrevSlide")!=null)
            $("GoPrevSlide").setAttribute("href","javascript:changeSlide(" + this.slideGroupId + ", -1);");
            
         if($("GoNextSlide")!=null)
            $("GoNextSlide").setAttribute("href","javascript:changeSlide(" + this.slideGroupId + ",  1);");
            
         $(this.currentSlideParent).style.position = "absolute";
         $(this.nextSlideParent).style.position = "absolute";
         this.ResizeContent();
      }
            
      this.registerCallback();
   },
   
   onMouseOver: function (ev) {
      this.paused = true;
   },
   
   onMouseOut: function (ev) {
      this.paused = false;
   },
   
   flip: function(direction){
      
      if (this.currentSlide == "dvFront" + this.slideGroupId){
         this.currentSlide = "dvBack" + this.slideGroupId;
         this.currentSlideParent = "dvBackParent" + this.slideGroupId;
         
         this.nextSlide = "dvFront" + this.slideGroupId;
         this.nextSlideParent = "dvFrontParent" + this.slideGroupId;

         $(this.nextSlideParent).style.zIndex = parseInt($(this.currentSlideParent).style.zIndex) - direction;
      } else {
         this.currentSlide = "dvFront" + this.slideGroupId;
         this.currentSlideParent = "dvFrontParent" + this.slideGroupId;
         
         this.nextSlide = "dvBack" + this.slideGroupId;
         this.nextSlideParent = "dvBackParent" + this.slideGroupId;
         
         $(this.currentSlideParent).style.zIndex = parseInt($(this.nextSlideParent).style.zIndex) + direction;
      }
   },
   
   registerCallback: function() {
      var callback = function () {
         this.advanceCached();
      }
      
      if (this.dynamic){
         this.fillCache();
         st[this.slideGroupId.toString()] = window.setTimeout(callback.bind(this), this.duration * 1000);
      }
    },
   
   showSlides: function(){
            
      var afterFinishCallback = (function(direction) {
         this.lastSlideId = this.upcomingSlideId;
         this.upcomingSlideId = -1;
         this.flip(direction);
         this.registerCallback();
      }).bind(this);
      
      this.lastTransitionTime = (new Date()).getTime();
               
      switch (this.transition) {
         case "SwapFade":  
            new Effect.Parallel([new Effect.Fade(this.currentSlide, {sync: true}), new Effect.Appear(this.nextSlide, {sync: true})], {duration: 1,afterFinish: afterFinishCallback(1)});
            break;
         case "CrossFade":
            //new Effect.Parallel([new Effect.BlindUp(this.currentSlide, {sync: true}), new Effect.BlindDown(this.nextSlide, {sync: false})], {duration: 3,afterFinish: afterFinishCallback(1)});
            window._timeoutID = setTimeout("Element.toggle('" + this.currentSlide + "')", 900);
            new Effect.BlindUp(this.currentSlide, {duration:1});
            new Effect.BlindDown(this.nextSlide, {duration:1, afterFinish: afterFinishCallback(1)});
            break;
         case "Puff":            
            Element.show(this.nextSlide);       
            new Effect.Puff(this.currentSlide, {duration:1, afterFinish: afterFinishCallback(-1)});
            break;
         case "BlindDown":
            setTimeout("Element.hide('" + this.currentSlide+ "')", 1000);
            new Effect.BlindDown(this.nextSlide, {duration:1, afterFinish: afterFinishCallback(1)});
            //setTimeout("Element.hide('" + this.currentSlide+ "')", 1000);
            //Spry.Effect.Slide(this.nextSlide, {duration:1000,from:'0%',to:'100%',toggle:false,finish:afterFinishCallback(1)});
            break;
         case "BlindUp":
            Element.show(this.nextSlide);
            setTimeout("Element.toggle('" + this.currentSlide + "')", 900);
            new Effect.BlindUp(this.currentSlide, {duration:1, afterFinish: afterFinishCallback(-1)});
            break;
         case "SwitchOff":
            Element.show(this.nextSlide);
            new Effect.SwitchOff(this.currentSlide, {duration:1, afterFinish: afterFinishCallback(-1)});
            break;
         case "DropOut":
            Element.show(this.nextSlide);
            new Effect.DropOut(this.currentSlide, {duration:1, afterFinish: afterFinishCallback(-1)});
            break;
         case "Squish":
            Element.show(this.nextSlide);
            new Effect.Squish(this.currentSlide, {duration:1, afterFinish: afterFinishCallback(-1)});
            break;
         case "Shrink":
            Element.show(this.nextSlide);
            setTimeout("Element.toggle('" + this.currentSlide + "')", 900);
            new Effect.Shrink(this.currentSlide, {duration:1, afterFinish: afterFinishCallback(-1)});
            break;                                                                        
         case "None":
            Element.hide(this.currentSlide);
            Element.show(this.nextSlide);
            afterFinishCallback(1);
            break;
      }
         
      this.ResizeContent();

   },
   
   ResizeContent: function()
   {
      var wasHidden = !Element.visible(this.currentSlide);
      if (wasHidden)
      if (this.transition == "SwapFade" || this.transition == "CrossFade" || this.transition ==  "BlindDown")
         Element.show(this.currentSlide); 
   
      // Mozilla
      if(navigator.userAgent.search("Firefox/") != -1 || navigator.userAgent.search("Opera/") != -1)
      {     
         var oldLeftPosition = $(this.currentSlide).style.left;   
         $(this.currentSlide).style.left = -10000;
         $(this.currentSlide).style.width = -100;
         $(this.currentSlide).style.height = -100;
         
         if (parseInt($(this.currentSlide).offsetWidth) >= parseInt($("dvContent" + this.slideGroupId).parentNode.offsetWidth))
         {
            $("dvContent" + this.slideGroupId).style.width = parseInt($(this.currentSlide).offsetWidth) + "px";
         }

         $("dvContent" + this.slideGroupId).style.height = (parseInt($(this.currentSlide).offsetHeight) + parseInt($(this.currentSlide).offsetTop)) + "px";
            
         $(this.currentSlide).style.left = oldLeftPosition;    
      }
      else
      //Internet Explorer Browser and Others
      //if(navigator.userAgent.search("MSIE") != -1)
      {        
         var oldWidth = $(this.currentSlide).style.width;
         $(this.currentSlide).style.width = 0;
         
         if (parseInt($(this.currentSlide).offsetWidth) >= parseInt($("dvContent" + this.slideGroupId).parentNode.offsetWidth))
         {
            $("dvContent" + this.slideGroupId).style.width = parseInt($(this.currentSlide).offsetWidth) + "px";
            $(this.currentSlide).style.width = parseInt($(this.currentSlide).offsetWidth) + "px";
         }
         else
         {
            $(this.currentSlide).style.width = oldWidth;
         }
         
         $("dvContent" + this.slideGroupId).style.height = parseInt($(this.currentSlide).offsetHeight) + "px";      
      }
      
      if (this.transition == "SwapFade" || this.transition == "CrossFade" || this.transition ==  "BlindDown")
      {
         if (wasHidden)
            Element.hide(this.currentSlide);
         else
         {
            Element.hide(this.nextSlide);   
         }
      }
   },

   fillCache: function ()
   {
      if (this.cachedSlides.length >= CacheSize)
         return;
      
      this.currentRequestId++;
      var requestSlideId = this.lastSlideId;
      if (this.cachedSlides.length > 0)
         requestSlideId = this.cachedSlides[this.cachedSlides.length - 1].Id;
            
      TECRRequestWithId('GetSlides', this.currentRequestId, this.slideGroupId, this.direction, requestSlideId, CacheSize, (function(res, id){
         // Abort if this response was expected since before the cache was invalidated
         if (id != this.currentRequestId)
         {
            return;
         }
         
         try 
         {
            // Make sure the browser brings related resources too
            var contentHTML = "";
            for (var index = 0; index < res.value.length; index++)
            {
               contentHTML += res.value[index].SlideContent;
            }
            
            $("dvContentCache" + this.slideGroupId).innerHTML = contentHTML;
            
            // Add the new content to the cache
            this.cachedSlides = this.cachedSlides.concat(res.value);
         } catch(ex){}
         
         // If a previous call to advanceCached had nothing to
         // do because the cache was empty, we call it again - now we have slides
         if (this.cacheWasEmpty && !this.paused)
         {
            // Make sure there is something in the cache, otherwise it will
            // result in an infinite call loop; we put a null that will throw
            // when used; the next call will still get here, but later, after the
            // timer interval passes
            if (this.cachedSlides.length == 0)
            {
               this.cachedSlides.push(null);
            }
            
            this.cacheWasEmpty = false;
            clearTimeout(st[this.slideGroupId.toString()]);
            this.advanceCached();
         }
       }).bind(this));     
      
   },
   
   advanceCached: function(){    
      if (this.paused) { this.registerCallback(); return; }
      
      if (this.cachedSlides.length > 0)
      {
         try
         {
            var target = $(this.nextSlide);
            var rmsli = this.cachedSlides.shift();
            this.upcomingSlideId = rmsli.Id;
            target.innerHTML = parseSlideLayout(this.customSlideLayout, rmsli.SlideContent, this.slideGroupId); 
         } catch (ex) {}
         
         if (target.innerHTML.length == 0) 
         {
            target.innerHTML = "No content defined, or content not enabled!";
         }
         
         if (this.restart > 0)
            this.restart = 0;
            
         this.direction = 0;     
         this.showSlides();
      }
      else
      {
         // We set this flag; fill cache will call advanceCached again
         // as soon as the slides are available
         this.cacheWasEmpty = true;
         this.registerCallback();
      }
             
   },
   
   advanceRaw: function(){    

      // Clear the cache
      this.cachedSlides = new Array();
      this.cacheWasInvalidated = true;
      this.currentRequestId++;
      
      TECRRequestWithId('GetSlide', this.currentRequestId, this.slideGroupId, this.direction, this.lastSlideId, (function(res, id){
         var target = $(this.nextSlide);
         try{
            var rmsli = res.value;
            this.upcomingSlideId = rmsli.Id;
            target.innerHTML = parseSlideLayout(this.customSlideLayout, rmsli.SlideContent, this.slideGroupId);                                  
         } catch(ex){}
         
         if (target.innerHTML.length == 0) {
            target.innerHTML = "No content defined, or content not enabled!";
         }

         this.showSlides();
       }).bind(this));     
       
       if (this.restart > 0){
         this.restart = 0;
       }
       this.direction = 0;    
       
   }

}

function parseSlideLayout(customSlideLayout, slideContent, slideGroupId){

   var tempContent;
   var pattern = ""; 
   var content = tempContent = customSlideLayout;
   var hasNextTag = false;
   var hasPreviousTag = false;
   
   //<SlideContent /> tag
   content = content.replace(/<SlideContent\s*\/>/gi, slideContent);
   
   //<next ... /> tag
   pattern = /<next\s?(.+?)\s?\/>/gi;
   if (pattern.test(content)){
      var nextTag = content.match(pattern)[0];

         var mouseOver = "";
         var mouseOut = "";
         var text = "";
         var css = "";
         var style = "";
         
         //mouseOver attribute
         pattern = /\smouseOver\s?=\s?"\s?(.+?)\s?"/gi;     
         if (pattern.test(nextTag)){
            mouseOver = nextTag.match(pattern)[0] || '';    
            mouseOver = mouseOver.replace(pattern, "$1");
         }
         
         //mouseOut attribute
         pattern = /\smouseOut\s?=\s?"\s?(.+?)\s?"/gi;
         if (pattern.test(nextTag)){
            mouseOut = nextTag.match(pattern)[0] || '';     
            mouseOut = mouseOut.replace(pattern, "$1");
         }
         
         //text attribute
         pattern = /\stext\s?=\s?"\s?(.+?)\s?"/gi; 
         if (pattern.test(nextTag)){
            text = nextTag.match(pattern)[0] || '';      
            text = text.replace(pattern, "$1");
         }
         
         //css attribute
         pattern = /\scss\s?=\s?"\s?(.+?)\s?"/gi;
         if (pattern.test(nextTag)){
            css = nextTag.match(pattern)[0] || '';    
            css = css.replace(pattern, "$1");
         }
         
         //style attribute
         pattern = /\sstyle\s?=\s?"\s?(.+?)\s?"/gi;
         if (pattern.test(nextTag)){
            style = nextTag.match(pattern)[0] || '';     
            style = style.replace(pattern, "$1");
         }
      
      var nextLink = "<a href=\"javascript:changeSlide(" + slideGroupId + ", 1);\"";
      if (css.length > 0){
         nextLink += " class=\"" + css + "\"";
      }
      if (style.length > 0){
         nextLink += " style=\"" + style + "\"";
      }  
      nextLink += " >";
            
         if (mouseOut.length > 0){
            nextLink += "<img src=\"" + mouseOut + "\" border=\"0\" alt=\"Next slide\" title=\"Next slide\"";
            if (mouseOver.length > 0){
               nextLink += " onMouseOver=\"this.src='" + mouseOver + "'\" onMouseOut=\"this.src='" + mouseOut + "'\"";
            }
            nextLink += " />";
         } else {
            nextLink += text;
         }
         
      nextLink += "</a>";
      
      hasNextTag = true;
   }
   
   
   //<previous ... /> tag
   pattern = /<previous\s?(.+?)\s?\/>/gi;
   if (pattern.test(content)){
      var previousTag = content.match(pattern)[0];
         
         pattern = "";
         
         mouseOver = "";
         mouseOut = "";
         text = "";
         css = "";
         style = "";
         
         //mouseOver attribute
         pattern = /\smouseOver\s?=\s?"\s?(.+?)\s?"/gi;     
         if (pattern.test(previousTag)){
            mouseOver = previousTag.match(pattern)[0] || '';      
            mouseOver = mouseOver.replace(pattern, "$1");
         }
         
         //mouseOut attribute
         pattern = /\smouseOut\s?=\s?"\s?(.+?)\s?"/gi;
         if (pattern.test(previousTag)){
            mouseOut = previousTag.match(pattern)[0] || '';    
            mouseOut = mouseOut.replace(pattern, "$1");
         }
         
         //text attribute
         pattern = /\stext\s?=\s?"\s?(.+?)\s?"/gi; 
         if (pattern.test(previousTag)){
            text = previousTag.match(pattern)[0] || '';     
            text = text.replace(pattern, "$1");
         }
         
         //css attribute
         pattern = /\scss\s?=\s?"\s?(.+?)\s?"/gi;
         if (pattern.test(previousTag)){
            css = previousTag.match(pattern)[0] || '';      
            css = css.replace(pattern, "$1");
         }
         
         //style attribute
         pattern = /\sstyle\s?=\s?"\s?(.+?)\s?"/gi;
         if (pattern.test(previousTag)){
            style = previousTag.match(pattern)[0] || '';    
            style = style.replace(pattern, "$1");
         }
      
      var previousLink = "<a href=\"javascript:changeSlide(" + slideGroupId + ", -1);\"";
      if (css.length > 0){
         previousLink += " class=\"" + css + "\"";
      }
      if (style.length > 0){
         previousLink += " style=\"" + style + "\"";
      }  
      previousLink += " >";
            
         if (mouseOut.length > 0){
            previousLink += "<img src=\"" + mouseOut + "\" border=\"0\" alt=\"Previous slide\" title=\"Previous slide\"";
            if (mouseOver.length > 0){
               previousLink += " onMouseOver=\"this.src='" + mouseOver + "'\" onMouseOut=\"this.src='" + mouseOut + "'\"";
            }
            previousLink += " />";
         } else {
            previousLink += text;
         }
         
      previousLink += "</a>";
      
      hasPreviousTag = true;
   }
   
   //replace tags with actual links
   if (hasNextTag){
      content = content.replace(/<next\s?(.+?)\s?\/>/gi, nextLink);
   }
   if (hasPreviousTag){
      content = content.replace(/<previous\s?(.+?)\s?\/>/gi, previousLink);
   }
   
   return content;
}

function changeSlide(slideGroupId, direction){

   if(!sr[slideGroupId.toString()].lastTransitionTime ||
    ((new Date()).getTime() - sr[slideGroupId.toString()].lastTransitionTime) > 1500) //miliseconds
   {
      clearTimeout(st[slideGroupId.toString()]);
         
      var oldDirection = sr[slideGroupId.toString()].direction;
      
      sr[slideGroupId.toString()].direction = direction;  
      var oldPaused = sr[slideGroupId.toString()].paused; 
      sr[slideGroupId.toString()].paused = false;
      sr[slideGroupId.toString()].advanceRaw();
      sr[slideGroupId.toString()].paused = oldPaused;
      
      //restore direction
      sr[slideGroupId.toString()].direction = oldDirection;
      sr[slideGroupId.toString()].lastTransitionTime = (new Date()).getTime();
   }  
}

