//************ Pane ************//
function Pane (id, title, loaded, url)
{
  this.id                = id;
  this.idInner           = id + "Inner";
  this.idImage           = id + "Image";
  this.idContent         = id + "Content";
  this.title             = title;
  this.positionNdx       = -1;
  this.opacity           = 100;
  this.hide              = false;              // if a pane will not be visible because it has rotate behind
                                               //  other panes, then do not perform any transformations on it
  this.bAutoSlide        = false;
  this.slides            = null;               // pagination data that may appear in top left of pane
  this.nextSlideName     = "";                 // if we need to go to another slide, this will be set
  this.timer             = null;               // used by autoStart in case we need to kill timer if the current pane scrolls out

  this.childContentPanes = null;

  this.loaded            = loaded;             // if content not loaded, the we need to ajax call to the given URL to load it
  this.url               = (url === undefined) ? "" : url;
}


//************ Slides ************//
function Slides (hiliteColor, slideData)
{
  this.hiliteColor       = hiliteColor;
  this.slideData         = slideData;           // array of display name, div name
  this.currentSlide      = 0;
  this.arrowImage        = "";                  // there are currently 4 different colored arrow images - image specified in call to slidesAdd
}


//************* CarouselMgr ************//
function CarouselMgr (carouselPanes, contentPanes)
{
  this.allPanes          = new Array();         // all panes that could be in the carousel
  this.panes             = new Array();         // array of pane objects (things that spin in the carousel)
  this.contentNames      = new Array();         // has the array that contains all known contentNames
  this.slideNames        = null;                // will have the array that contains all known slideNames after initSlides is called
  this.positionNdx       = -1;                  // displayPosition of the last pane to be clicked that causes the carousel to rotate
  this.loadAttempts      = 0;
  this.previousPane      = "";                  // remembers that last pane viewed for the goBack function
  this.currentPane       = "makeup";
  this.nextContentName   = "";                  // set by goToPane when switching content in the utility pane
  this.currentContent    = -1;

  jQuery("#" + carouselPanes +">div")           // get direct children only
    .css   ("position",         "absolute")
    .css   ("background-color", "black")
    .css   ("width",            "816px")
    .css   ("height",           "401px")
    .css   ("overflow",         "hidden")
    .hide  ()
    .bind ("click", function(event)
    {
      //  the new current pane
      contentId = event.target.id.replace(/Image/, "Content");
      jQuery("#" + contentId).fadeOut("fast");

      var pane = carouselMgr.panes[carouselMgr.getPaneNdxByName (carouselMgr.panes, this.id)];

      // save the position of the pane that was clicked - we'll need to set the opacity of the new pane
      //  that will occupy that position, so we have to save this position to know which pane to set
      carouselMgr.positionNdx = pane.positionNdx;

      // rotate carousel to show new current pane
      carouselMgr.goToPane (this.id);
    })
    .mouseover (function()
    {
      jQuery(this).css("cursor", "pointer");
      carouselMgr.opacityIncrease (this.id);
    })
    .mouseout (function()
    {
      jQuery(this).css("cursor", "default");
      carouselMgr.opacityRestore (this.id);
    });

  // set up logic that pauses, restarts and stops callback functionality for current pane
  //  mouseovers pause, mouseout restarts, mouse clicks discontinues callbacks
  jQuery("div[id$=Content]")
    .bind ("click", function(event)
    {
      if ((carouselMgr.panes[0].bAutoSlide) && (carouselMgr.timer != null))
      {
        clearTimeout (carouselMgr.timer);
        carouselMgr.timer = null;
      }
    })
    .bind ("mouseover", function()
    {
      if ((carouselMgr.panes[0].bAutoSlide) && (carouselMgr.timer != null))
      {
        clearTimeout (carouselMgr.timer);
        carouselMgr.timer = null;
      }
    })
    .bind ("mouseout", function()
    {
      if (carouselMgr.panes[0].bAutoSlide)
        carouselMgr.timer = setTimeout ("carouselMgr.autoSlide()", 12000);
    });

  // set up resize handler to recenter carousel
  jQuery(window).bind('resize',function()
  {
    if (siteFullyLoaded)
    {
      // if reportDimension adds a scrollbar, then the we want to push the carousel over another 10 pixels
      var windowWidth = jQuery().width();
      if (jQuery().height() < MIN_HEIGHT)
        windowWidth -= 20;
      if (windowWidth < MIN_WIDTH)
        windowWidth = MIN_WIDTH;

      carousel.reinitPanePositions(windowWidth / 2);
      jQuery("#contentPanes"     ).css ("left", parseInt($(carouselMgr.panes[0].id).style.left));
      jQuery("#sliderPagination" ).css ("left", parseInt($(carouselMgr.panes[0].id).style.left));
      jQuery("#waitPanel"        ).css ("left", parseInt($(carouselMgr.panes[0].id).style.left) + 2);
      jQuery("#storeLocWaitImage").css ("left", parseInt($(carouselMgr.panes[0].id).style.left) + 350);
    }
  });

  // hide all content panes -- will display only the center pane's content soon
  jQuery("#" + contentPanes +">div").hide ();
}

var initialAnimation = false;
var ndxAnimation     = 1;

//animateIntro();
CarouselMgr.prototype.animateIntro = function ()
{
  if (ndxAnimation == 1)
  {
    carousel.reinitPanes(splashPanes);

    jQuery("#splashPanes img").css("opacity", 1.0);

    setTimeout ('carousel.rotate (1, true)', 1000);
    ndxAnimation++;
  }
  else
  {
    if (ndxAnimation <= 4)
    {
      carousel.rotate (1, true);
      ndxAnimation++;
    }
    else
    {
      initialAnimation = false;

      for (ndx = 0; ndx < this.panes.length; ndx++)
        jQuery("#"+this.panes[ndx].id).show();
      jQuery("#"+this.panes[0].idContent).fadeIn("slow");

      this.displayPagination();

      jQuery("#splashPanes").fadeTo(0.0, "normal", function(){jQuery(this).css("display","none")});
      carousel.reinitPanes(this.panes);
      siteFullyLoaded = true;
    }
  }
}


// autoStart
CarouselMgr.prototype.autoSlide = function ()
{
  if (this.timer != null)
    clearTimeout (this.timer);
  if (this.panes[0].bAutoSlide)
  {
    if (this.panes[0].slides.currentSlide < this.panes[0].slides.slideData.length - 1)
    {
      this.slidePane (this.panes[0].slides.currentSlide + 1, false);
      this.timer = setTimeout ("carouselMgr.autoSlide()", 12000);
    }
    else
    {
      if (this.panes[0].slides.currentSlide == this.panes[0].slides.slideData.length - 1)
      {
        carouselMgr.slidePane(0, false);
        this.timer = null;
        this.panes[0].bAutoSlide = false;
      }
    }
  }
}


// autoStop
CarouselMgr.prototype.autoStop = function ()
{
  if (this.timer != null)
  {
    clearTimeout (this.timer);
    this.timer = null;
  }
  this.allPanes[this.getPaneNdxByName (this.allPanes, "makeup")].bAutoSlide = false;
}


// buildCurrentList
CarouselMgr.prototype.buildCurrentList = function (ndxCenterPane)
{
  var nAllPanes = this.allPanes.length;
  var ndx;

  for (ndx = 0; ndx < 5; ndx++)
    this.panes[ndx] = this.allPanes[(ndxCenterPane + ndx) % nAllPanes];

  for (ndx = 1; ndx < 6; ndx++)
    this.panes[10 - ndx] = this.allPanes[((ndxCenterPane - ndx) + nAllPanes) % nAllPanes];
}


CarouselMgr.prototype.contentAdd = function(paneName, childContentPanes)
{
  var ndx;
  var pane               = this.allPanes[this.getPaneNdxByName (this.allPanes, paneName)];
  pane.childContentPanes = childContentPanes;
  //pane.currentContent    = 0;

  // hide all content panes except the first one
  for (ndx = 1; ndx < childContentPanes.length; ndx++)
    jQuery ("#" + childContentPanes[ndx].contentName).css("opacity", 0).css("left", "2000px");

  // add content panes to the known panes that the UrlMgr can translate and goToPane can go to
  for (ndx = 0; ndx < childContentPanes.length; ndx++)
    this.contentNames.push(childContentPanes[ndx].contentName);
}


CarouselMgr.prototype.displayContent = function()
{
  this.displayPagination();
  jQuery("#"+this.panes[0].idContent).fadeIn("slow");
  jQuery("#"+this.panes[0].idImage)  .hide  ();
}


CarouselMgr.prototype.displayPagination = function()
{
  var paginationStr;
  var slides        = this.panes[0].slides;

  if (slides != null)
  {
    if ((slides.slideData[slides.currentSlide].displayText != "") && (slides.slideData[slides.currentSlide].slideName != ""))
    {
      paginationStr = this.getPaginationText ();
      jQuery("#sliderPaginationText").html  (paginationStr);
      if (paginationStr != "")
      {
        jQuery("#sliderPaginationArrow").css    ("opacity", 0.0);
        jQuery("#sliderPagination")     .fadeIn ("slow", function(){carouselMgr.displayPaginationArrow();});
      }
    }
  }
}


CarouselMgr.prototype.displayPaginationArrow = function()
{
  if (this.panes[0].slides != null)
  {
    var arrowPosition = (jQuery(".currentSlide").width() / 2) + jQuery(".currentSlide")[0].offsetLeft + 16;
    jQuery("#sliderPaginationArrow")     .css    ("left", arrowPosition);
    jQuery("#sliderPaginationArrowImage").attr   ("src",  this.panes[0].slides.arrowImage);
    jQuery("#sliderPaginationArrow")     .fadeTo ("slow", 1.0);
  }
}


CarouselMgr.prototype.getCurrentPane = function()
{
  return (this.currentPane);
}


CarouselMgr.prototype.getPaginationText = function()
{
  var paginationStr = "";
  var slides        = this.panes[0].slides;
  var slideName     = slides.slideData[0].slideName;
  var displayText   = slides.slideData[0].displayText;
  var slideNumber   = 2;

  if ((slides != null) && (slides.slideData[slides.currentSlide].bShow))
  {
    if (slides.currentSlide == 0)
    {
      paginationStr = '<span class="currentSlide" style="padding-left:6px; padding-right:6px; color:' + slides.hiliteColor + '">'
                    + displayText
                    + '</span>'
                    + '<img src="images/nav/nav_divider.gif" width="2" height="12"/>';
    }
    else
    {
      if (slideName.indexOf("Landing") != -1)
        slideName = slideName.substring (0, slideName.indexOf("Landing"));
      paginationStr = '<a href="#MAX_' + slideName + '" onclick="carouselMgr.goToPane(\'' + slideName + '\')" style="padding-left:6px; padding-right:6px">'
                    + displayText
                    + '</a>'
                    + '<img src="images/nav/nav_divider.gif" width="2" height="12"/>';
    }

    for (ndx = 1; ndx < slides.slideData.length; ndx++)
    {
      slideName   = slides.slideData[ndx].slideName;
      displayText = slides.slideData[ndx].displayText;

      if (slides.currentSlide == ndx)
      {
        paginationStr += '<span class="currentSlide" style="padding-left:6px; padding-right:6px; color:' + slides.hiliteColor + '">';
        paginationStr += displayText;
        paginationStr += '</span>';
      }
      else
        paginationStr += '<a href="#MAX_' + slideName + '" onclick="carouselMgr.goToPane(\'' + slideName + '\')" title=" ' + displayText + ' " style="padding-left:6px; padding-right:6px">' + slideNumber + '</a>';
      slideNumber++;

      if (ndx < slides.slideData.length - 1)
        paginationStr += '<img src="images/nav/nav_divider.gif" width="2" height="12"/>';
    }
  }
  return (paginationStr);
}


// getPaneNdxByContentName
CarouselMgr.prototype.getPaneNdxByContentName = function (contentName)
{
  var bWorkToDo = true;
  var ndx       = 0;
  var pane;

  while (bWorkToDo)
  {
    pane = this.allPanes[ndx];
    if (this.getContentNdxByContentName (contentName, pane) != -1)
      bWorkToDo = false;
    else
    {
      ndx++;
      if (ndx >= this.allPanes.length)
      {
        ndx = -1;
        bWorkToDo = false;
      }
    }
  }
  return (ndx);
}


// getContentNdxByContentName
CarouselMgr.prototype.getContentNdxByContentName = function (contentName, pane)
{
  var bWorkToDo = true;
  var ndx       = 0;

  if (pane.childContentPanes == null)
  {
    bWorkToDo = false;
    ndx       = -1;
  }

  while (bWorkToDo)
  {
    if (pane.childContentPanes[ndx].contentName == contentName)
      bWorkToDo = false;
    else
    {
      ndx++;
      if (ndx >= pane.childContentPanes.length)
      {
        ndx = -1;
        bWorkToDo = false;
      }
    }
  }
  return (ndx);
}


// getPaneNdxByName
CarouselMgr.prototype.getPaneNdxByName = function(panesArray, paneName)
{
  var bWorkToDo = true;
  var ndx       = 0;

  while (bWorkToDo)
  {
    if (panesArray[ndx].id == paneName)
      bWorkToDo = false;
    else
    {
      ndx++;
      if (ndx >= panesArray.length)
      {
        ndx = -1;
        bWorkToDo = false;
      }
    }
  }
  return (ndx);
}


// getPaneNdxByPosition
CarouselMgr.prototype.getPaneNdxByPosition = function (positionNdx)
{
  var bWorkToDo = true;
  var ndx       = 0;

  while (bWorkToDo)
  {
    if (this.panes[ndx].positionNdx == positionNdx)
      bWorkToDo = false;
    else
    {
      ndx++;
      if (ndx >= this.panes.length)
      {
        ndx = -1;
        bWorkToDo = false;
      }
    }
  }
  return (ndx);
}


// getPaneNdxBySlideName
CarouselMgr.prototype.getPaneNdxBySlideName = function (slideName)
{
  var bWorkToDo = true;
  var ndx       = 0;

  while (bWorkToDo)
  {
    //logDebug (this.slideNames[ndx].slideName + " " + slideName);
    if (this.slideNames[ndx].slideName == slideName)
    {
      ndx       = this.getPaneNdxByName (this.allPanes, this.slideNames[ndx].paneName)
      bWorkToDo = false;
    }
    else
    {
      ndx++;
      if (ndx >= this.slideNames.length)
      {
        ndx = -1;
        bWorkToDo = false;
      }
    }
  }
  return (ndx);
}


// getSlideNdxBySlideName
CarouselMgr.prototype.getSlideNdxBySlideName = function (slideName, pane)
{
  var slides    = pane.slides;
  var bWorkToDo = true;
  var ndx       = 0;

  if (slides == null)
  {
    bWorkToDo = false;
    ndx       = -1;
  }

  while (bWorkToDo)
  {
    if (slides.slideData[ndx].slideName == slideName)
      bWorkToDo = false;
    else
    {
      ndx++;
      if (ndx >= slides.slideData.length)
      {
        ndx = -1;
        bWorkToDo = false;
      }
    }
  }
  return (ndx);
}


// goBack
// TODO paneName is not used
CarouselMgr.prototype.goBack = function (paneName)
{
  if (this.previousPane != "")
    this.goToPane (this.previousPane);
}


// goToPane
CarouselMgr.prototype.goToPane = function (paneName)
{
  var ndxSlide      = -1;
  var ndxContent    = -1;
  var bSlide        = false;
  var nAllPanes;
  var ndx;
  var ndxAll;
  var pane;
  var strCI;
  var title;

  // hide the ratings div that is displayed on the product
  // details pages.
  jQuery("#ratings").hide ();
  jQuery("#BVSubmissionFrame").attr({src: ""});

  // if we were autoSliding, stop
  if (this.currentPane.indexOf("makeup") != -1)
    this.autoStop();

  // remove the video player from the display whenever we change panels
  jQuery('#blushVideoImage').css('display','block');
  jQuery('#blushVideoMovie').css('display','none');
  if (thisMovie("blushMovie").playMovie !== undefined)
    thisMovie("blushMovie").playMovie("");

  // handle all the special cases before "real" processing begins
  if (paneName == "")
  {
    paneName = "makeup";
  }
  if (paneName == "buyOnline")
  {
    strCI = shoppingCartMgr.getCIstring ();
    if (strCI != "")
      jQuery("#buyOnlineFrame").attr({src: "buyOnline.jsp?" + escape(strCI)});
  }
  if ((paneName == "storeLocator") || ((paneName == "utility") && (this.currentContent == -1)))
    jQuery("#resultsFrame").attr({src: "whereToBuy.jsp"});

  if (paneName == "makeupAdvisor")
  {
    paneName = "contactUs";
    setTimeout ("showContactUs()", 1000);
  }

  if (paneName == "register")
  {
    register('registerMainContainer', 'consumerSurveyForm');
  }
  else
  if (paneName == "login")
  {
    login('loginMainContainer', 'loginForm');
  }
  else

  // if we're already on the new pane, just do nothing
  if (this.currentPane != paneName)
  {
    // disable url change detection logic until goToPane has completed
    urlMgr.disableUrlDetection ();
    //urlMgr.urlDetectEnabled = false;

    // track this action
    trackPane (paneName);

    this.unloadSpecialCasePane(paneName);

    // if the pane we're going to is the previous pane, then there will be no previous pane
    //  this will happen when the goBack function is called to goToPane
    this.previousPane = (this.previousPane == paneName) ? "" : this.currentPane;
    this.currentPane  = paneName;

    // special case - the utility panel can be rotate by clicking on it in the carousel
    //  but typically a child content panel will be request
    if (paneName == "utility")
      ndxAll = -1;
    else
      ndxAll = this.getPaneNdxByName (this.allPanes, paneName);

    // see if the new pane is a pane (or one of the content or slides)
    if (ndxAll == -1)
    {
      // the request pane isn't a pane, so the request must be for a specific slide or a specific child content pane
      ndxAll        = this.getPaneNdxBySlideName (paneName);
      if (ndxAll != -1)
      {
        //  ok it is a slide, so rotate to that pane, wait until it's in place, then display the correct slide
        this.allPanes[ndxAll].nextSlideName = paneName;
        ndx         = this.getPaneNdxByName (this.panes, this.allPanes[ndxAll].id);
      }

      // see if it was a slide - if not, then it must be a content child
      if (ndxAll == -1)
      {
        if (this.currentContent == -1)
          this.currentContent = 0;
        if (paneName == "utility")
        {
          ndxAll      = this.getPaneNdxByName           (this.allPanes, paneName);
          pane        = this.allPanes[ndxAll];
          ndxContent  = this.currentContent;
        }
        else
        {
          ndxAll      = this.getPaneNdxByContentName    (paneName);
          if (ndxAll == -1)
            document.location.href = "/error404.jsp";
          pane        = this.allPanes[ndxAll];
          ndxContent  = this.getContentNdxByContentName (paneName, pane);
        }
        ndx           = this.getPaneNdxByName           (this.panes, this.allPanes[ndxAll].id);
        paneName      = pane.childContentPanes[ndxContent].contentName;

        // if correct pane is already displayed, and we just need to switch content: do the fade in / out thing
        //  otherwise just swap them out before the correct pane is rotated into view
        if (this.currentContent != ndxContent)
        {
          var currentContentPane = pane.childContentPanes[this.currentContent].contentName;
          this.currentContent    = ndxContent;
          this.nextContentName   = pane.childContentPanes[ndxContent].contentName;

          if (ndx == 0)
          {
            jQuery ("#" + currentContentPane).fadeTo(600, 0.0,
              function()
              {
                jQuery (this).css("left", "2000px");
                jQuery ("#" + carouselMgr.nextContentName).css("left", "0px").fadeTo(600, 1.0);
                jQuery ("#utilityImage").attr("src", "/images/carousel/pnl_" + carouselMgr.nextContentName + ".jpg");
              }
            );
          }
          else
          {
            jQuery ("#" + currentContentPane).css("left", "2000px");
            jQuery ("#" + carouselMgr.nextContentName).css("left", "0px").css("opacity", 1.0);
            jQuery ("#utilityImage").attr("src", "/images/carousel/pnl_" + carouselMgr.nextContentName + ".jpg");
          }
        }
      }
    }
    else
    {
      ndx = this.getPaneNdxByName (this.panes, paneName);
    }

    // check if we have to rotate carousel or just slide or change the content
    if (ndx != 0)
    {
      // current pane must change, so hide the pagination, and content in preparation to rotate
      if (this.panes[0].slides != null)
        jQuery("#sliderPagination").fadeOut ("slow");

      jQuery("#"+this.panes[0].idImage)  .show    ();
      jQuery("#"+this.panes[0].idContent).hide    ();
    }

    if (ndx != 0)
    {
      // pane is not already in carousel or it's in the back so we can just rotate to it
      // if ndx == -1 then we must rebuild array --- either the carousel is in the back or not in the current carousel array
      if ((ndx == -1) || ((ndx >= 3) && (ndx <= 7)))
      {
        this.buildCurrentList(ndxAll + 2);

        // init these new panes so that they will be displayed with correct sizes and positions
        this.reinitPanes ();
        ndx = 8;
      }
      //jQuery("#"+this.panes[ndx].idImage).hide    ();

      this.setPageTitle(this.panes[ndx]);
      carousel.goToPaneNdx (ndx);
    }
    else
    {
      // TODO: check if all vars in this function are still being used
      var slides     = this.panes[0].slides;
      if (slides != null)
      {
        if (slides.slideData[slides.currentSlide].slideName != paneName)
        {
          this.panes[0].nextSlideName = paneName;
          this.doSlidePane(false);
        }
        else
          this.runSlideInit();
      }
      doNav       (carouselMgr.getNormalizedPaneName());
      doCallout   (carouselMgr.getNormalizedPaneName());
      doFooterBBB (carouselMgr.getNormalizedPaneName());
      this.setPageTitle(this.panes[0]);
    }
  }
}

CarouselMgr.prototype.unloadSpecialCasePane = function (paneName)
{
  if ((this.currentPane.indexOf("nightOut")         != -1) && (paneName.indexOf("nightOut")         == -1))
  {
    jQuery("#nightOutContent").html("");
    this.allPanes[this.getPaneNdxByName (this.allPanes, "nightOut")].loaded = false;
  }
  if ((this.currentPane.indexOf("firstImpressions") != -1) && (paneName.indexOf("firstImpressions") == -1))
  {
    jQuery("#firstImpressionsContent").html("");
    this.allPanes[this.getPaneNdxByName (this.allPanes, "firstImpressions")].loaded = false;
  }
  if ((this.currentPane.indexOf("sultryResults")    != -1) && (paneName.indexOf("sultryResults")    == -1))
  {
    jQuery("#sultryResultsContent").html("");
    this.allPanes[this.getPaneNdxByName (this.allPanes, "sultryResults")].loaded = false;
  }
  if ((this.currentPane.indexOf("byInvitationOnly") != -1) && (paneName.indexOf("byInvitationOnly") == -1))
  {
    jQuery("#byInvitationOnlyContent").html("");
    this.allPanes[this.getPaneNdxByName (this.allPanes, "byInvitationOnly")].loaded = false;
  }
  if ((this.currentPane.indexOf("runwayInspired")   != -1) && (paneName.indexOf("runwayInspired")   == -1))
  {
    jQuery("#runwayInspiredContent").html("");
    this.allPanes[this.getPaneNdxByName (this.allPanes, "runwayInspired")].loaded = false;
  }
}


CarouselMgr.prototype.setPageTitle = function (pane)
{
  var title = pane.title;
  if (pane.childContentPanes != null)
    title = pane.childContentPanes[this.currentContent].title;

  if (title == "")
    title = "Makeup Expert Tips, Advice and Products at MAXFactor.com";
  document.title = title;
}


// goToPaneComplete
CarouselMgr.prototype.goToPaneComplete = function ()
{
  if (initialAnimation == false)
  {
    var n           = this.getPaneNdxByPosition (0);
    n               = this.getPaneNdxByName     (this.allPanes, this.panes[n].id);

    // rebuild the pane array with this new pane as the first item in the array
    this.buildCurrentList (n);
    this.reinitPanes      ();

    //for (var ndx=0; ndx< this.panes.length; ndx++)
    //  logDebug (this.panes[ndx].id + " " + this.panes[ndx].positionNdx);

    // when we move the pane from underneath the mouse and move a new one into that spot under the mouse
    //  we want to have the new pane hilite just like when we mouse over a pane
    // we only have to do this when a pane is clicked on (and this.positionNdx is set), not when goToPane
    //  is called externally
    if (this.positionNdx != -1)
    {
      //divName = this.panes[this.getPaneNdxByPosition (this.positionNdx)].idInner;
      divName = this.panes[this.getPaneNdxByPosition (this.positionNdx)].idImage;
      //setOpacity (divName, 100);
      this.positionNdx = -1; // done
    }

    jQuery("#"+this.panes[0].idImage  ).hide   ();
    jQuery("#"+this.panes[0].idContent).fadeIn ("normal", function ()
                                                          {
                                                            doNav       (carouselMgr.getNormalizedPaneName());
                                                            doCallout   (carouselMgr.getNormalizedPaneName());
                                                            doFooterBBB (carouselMgr.getNormalizedPaneName());

                                                            carouselMgr.doSlidePane (true);

                                                            setTimeout("carouselMgr.displayPagination()", 100);
                                                          }
                                               );

  }
  else
  {
    setTimeout ('carouselMgr.animateIntro ()', 1000);
    //carouselMgr.animateIntro ();
  }
}


CarouselMgr.prototype.initPanes = function (contentPanes)
{
  var tmpLeft;
setCookie("initPanes", "" + (parseInt("0" + getCookieValue("initPanes")) + 1), 1);
//debugger;
  // if reportDimension adds a scrollbar, then the we want to push the carousel over another 10 pixels
  var windowWidth = jQuery().width();
  if (jQuery().height() < MIN_HEIGHT)
    windowWidth -= 20;
  if (windowWidth < MIN_WIDTH)
    windowWidth = MIN_WIDTH;

  // initialize carousels array with the first 10 panes
  // get just 10 panes to pass to the carousel - the carousel can only effectively rotate 10
  //  get the first 5 and last 5 panes
  this.buildCurrentList (0);

  // ok, now that the carousel array is ready, call the carousel
  carousel = new Carousel (windowWidth / 2, this.panes);

  // set the contentPaneContainer to be in the same spot as the center pane in the carousel
  // no sure why I can't call getLeft from lll or jQuery, but this works
  tmpLeft = parseInt($(this.panes[0].id).style.left);
  jQuery("#" + contentPanes  ).css ("left", tmpLeft);
  jQuery("#sliderPagination" ).css ("left", tmpLeft);
  jQuery("#waitPanel"        ).css ("left", tmpLeft + 2);
  jQuery("#storeLocWaitImage").css ("left", tmpLeft + 350);

  // now show only the carousel panes that will be displayed initially and display the center pane's content
  if (initialAnimation == false)
    for (ndx = 0; ndx < this.panes.length; ndx++)
      jQuery("#"+this.panes[ndx].id).show();

  // SPLASH - now done after animation
  // display content for the pane that is front and center
  if (initialAnimation == false)
  {
    jQuery("#"+this.panes[0].idContent).fadeIn("slow");
    jQuery("#"+this.panes[0].idImage)  .hide  ();
  }

  // SPLASH
  if (initialAnimation == false)
    this.displayPagination ();

  // hide all contentPanes except the first one
  for (ndx = 1; ndx < this.contentNames.length; ndx++)
    jQuery("#" + this.contentNames[ndx]).css ("left", "816px");

  // SPLASH - now done after animation
  //this.initSlides ();

  // SPLASH
  if (initialAnimation == false)
    jQuery("#splashPanes").hide();

  this.initSlides ();
}


CarouselMgr.prototype.initSplash = function ()
{
  var tmpLeft = parseInt($(this.panes[0].id).style.left);

  jQuery("#splashPanes div") .css ({left:tmpLeft, position:"absolute"});
  /*
  jQuery("#splash1") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash2") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash3") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash4") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash5") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash6") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash7") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash8") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash9") .css ({left:tmpLeft, position:"absolute"});
  jQuery("#splash10").css ({left:tmpLeft, position:"absolute"});
  */
}


CarouselMgr.prototype.initSlides = function ()
{
  this.slideNames = new Array (
    {slideName: "CovergirlInitial",                       paneName: "makeup"},
    {slideName: "CovergirlEyes",                          paneName: "makeup"},
    {slideName: "CovergirlLips",                          paneName: "makeup"},
    {slideName: "CovergirlFace",                          paneName: "makeup"},
    {slideName: "featuresShopOnline",                     paneName: "makeup"},
    {slideName: "featuresGallery",                        paneName: "makeup"},
    {slideName: "latestPromotionsOffers",                 paneName: "latestPromotions"},
    {slideName: "latestPromotionsReviewToWinSweeps",      paneName: "latestPromotions"},
    {slideName: "latestPromotionsBlush",                  paneName: "latestPromotions"},
    {slideName: "latestPromotionsBlushSweeps",            paneName: "latestPromotions"},
    {slideName: "latestPromotionsBlushVideos",            paneName: "latestPromotions"},
    {slideName: "latestPromotionsFallFaves",              paneName: "latestPromotions"},
    {slideName: "maxEyeShadows",                          paneName: "eye-shadow"},
    {slideName: "vividImpactEyeshadowDuo",                paneName: "eye-shadow"},
    {slideName: "maxEyeLiner",                            paneName: "eyeliner"},
    {slideName: "vividImpactHighlightingMascara",         paneName: "mascara"},
    {slideName: "volumeCoutureWaterproofMascara",         paneName: "mascara"},
    {slideName: "volumeCoutureMascara",                   paneName: "mascara"},
    {slideName: "lashPerfectionWaterproofMascara",        paneName: "mascara"},
    {slideName: "lashPerfectionMascara",                  paneName: "mascara"},
    {slideName: "lashLiftMascara",                        paneName: "mascara"},
    {slideName: "lashLiftWaterproofMascara",              paneName: "mascara"},
    {slideName: "stretchAndSeparateMascara",              paneName: "mascara"},
    {slideName: "stretchAndSeparateWaterproofMascara",    paneName: "mascara"},
    {slideName: "2000CalorieStraightBrushMascara",        paneName: "mascara"},
    {slideName: "2000CalorieCurvedBrushMascara",          paneName: "mascara"},
    {slideName: "2000CalorieAquaLashMascara",             paneName: "mascara"},
    {slideName: "noColorMascara",                         paneName: "mascara"},
    {slideName: "2000CalorieExtremeLashPlumper",          paneName: "lash-plumper"},
    {slideName: "2000CalorieExtremeWPLashPlumper",        paneName: "lash-plumper"},
    {slideName: "lashCurler",                             paneName: "eyeTools"},
    {slideName: "maxEyeShadowBrush",                      paneName: "eyeTools"},
    {slideName: "removerForLongLastingMakeup",            paneName: "eyeTools"},
    {slideName: "maxWearLipColors",                       paneName: "lipLongwearColors"},
    {slideName: "lipfinityLipstick",                      paneName: "lipLongwearColors"},
    {slideName: "colourPerfectionLipstick",               paneName: "lipstick"},
    {slideName: "vividImpactLipColor",                    paneName: "lipstick"},
    {slideName: "maxaliciousGlitz",                       paneName: "lip-gloss"},
    {slideName: "maxaliciousGlaze",                       paneName: "lip-gloss"},
    {slideName: "highDefinitionLipLiner",                 paneName: "lipLiners"},
    {slideName: "vividImpactLipliner",                    paneName: "lipLiners"},
    {slideName: "LipTools_removerForLongLastingMakeup",   paneName: "lipTools"},
    {slideName: "eraceSecretCoverUp",                     paneName: "concealer"},
    {slideName: "colorGeniusFoundationWithMinerals",      paneName: "foundation-makeup"},
    {slideName: "lastingPerformanceLiquidMakeup",         paneName: "foundation-makeup"},
    {slideName: "whippedCremeFluidMakeup",                paneName: "foundation-makeup"},
    {slideName: "silkPerfectionLiquidToPowderFoundation", paneName: "foundation-makeup"},
    {slideName: "panCakeWaterActivatedFoundation",        paneName: "foundation-makeup"},
    {slideName: "panStikUltraCreamyMakeup",               paneName: "foundation-makeup"},
    {slideName: "colorGeniusPressedPowder",               paneName: "powder-makeup"},
    {slideName: "colorGeniusBronzer",                     paneName: "blush"},
    {slideName: "colorGeniusBlush",                       paneName: "blush"},
    {slideName: "FaceTools_blushBrush",                   paneName: "faceTools"},
    {slideName: "FaceTools_cosmeticApplicationSponges",   paneName: "faceTools"},
    {slideName: "FaceTools_removerForLongLastingMakeup",  paneName: "faceTools"},
    {slideName: "plumperLashes",                          paneName: "eyeInsight"},
    {slideName: "maximizeEyeShape",                       paneName: "eyeInsight"},
    {slideName: "eyelinerTip",                            paneName: "eyeInsight"},
    {slideName: "preventCreasing",                        paneName: "eyeInsight"},
    {slideName: "pluckingEyebrows",                       paneName: "eyeInsight"},
    {slideName: "lipstickOnTeeth",                        paneName: "loveYourLips"},
    {slideName: "waxing",                                 paneName: "loveYourLips"},
    {slideName: "extraSoftLips",                          paneName: "loveYourLips"},
    {slideName: "scarsBlemishes",                         paneName: "faceBasics"},
    {slideName: "porePrep",                               paneName: "faceBasics"},
    {slideName: "powder101",                              paneName: "faceBasics"},
    {slideName: "blushBasics",                            paneName: "faceBasics"},
    {slideName: "makeupExpiration",                       paneName: "toolTipsTricks"},
    {slideName: "brushCleaning",                          paneName: "toolTipsTricks"},
    {slideName: "sharpeningLiners",                       paneName: "toolTipsTricks"},
    {slideName: "nightOut_volumeCouture",                 paneName: "nightOut"},
    {slideName: "nightOut_nightclubbing",                 paneName: "nightOut"},
    {slideName: "nightOut_smokyBrightEye",                paneName: "nightOut"},
    {slideName: "nightOut_spicyBlend",                    paneName: "nightOut"},
    {slideName: "nightOut_alluringLipfinity3D",           paneName: "nightOut"},
    {slideName: "firstImpressions_perfectPink",           paneName: "firstImpressions"},
    {slideName: "firstImpressions_rosyAndWarm",           paneName: "firstImpressions"},
    {slideName: "firstImpressions_girlNextDoor",          paneName: "firstImpressions"},
    {slideName: "firstImpressions_softShimmer",           paneName: "firstImpressions"},
    {slideName: "firstImpressions_autumnEffect",          paneName: "firstImpressions"},
    {slideName: "firstImpressions_neutralHues",           paneName: "firstImpressions"},
    {slideName: "firstImpressions_naturalBlush",          paneName: "firstImpressions"},
    {slideName: "sultryResults_layeredLip",               paneName: "sultryResults"},
    {slideName: "sultryResults_parisianNight",            paneName: "sultryResults"},
    {slideName: "sultryResults_bronzeRavenous",           paneName: "sultryResults"},
    {slideName: "sultryResults_vividViolets",             paneName: "sultryResults"},
    {slideName: "sultryResults_temptingFate",             paneName: "sultryResults"},
    {slideName: "sultryResults_boldBronzer",              paneName: "sultryResults"},
    {slideName: "byInvitationOnly_artShow",               paneName: "byInvitationOnly"},
    {slideName: "byInvitationOnly_blackTie",              paneName: "byInvitationOnly"},
    {slideName: "byInvitationOnly_dinnerParty",           paneName: "byInvitationOnly"},
    {slideName: "byInvitationOnly_openingNight",          paneName: "byInvitationOnly"},
    {slideName: "byInvitationOnly_acousticSet",           paneName: "byInvitationOnly"},
    {slideName: "byInvitationOnly_eveningWedding",        paneName: "byInvitationOnly"},
    {slideName: "runwayInspired_smoothSailing",           paneName: "runwayInspired"},
    {slideName: "runwayInspired_highlightingHues",        paneName: "runwayInspired"},
    {slideName: "runwayInspired_africanViolet",           paneName: "runwayInspired"},
    {slideName: "runwayInspired_africanVioletTwist",      paneName: "runwayInspired"},
    {slideName: "runwayInspired_queenBee",                paneName: "runwayInspired"},
    {slideName: "runwayInspired_queenBeeTwist",           paneName: "runwayInspired"},
    {slideName: "runwayInspired_serengeti",               paneName: "runwayInspired"},
    {slideName: "runwayInspired_lioness",                 paneName: "runwayInspired"},
    {slideName: "strikingDramatic",                       paneName: "makeup-trends"},
    {slideName: "flawlessFlushAngelic",                   paneName: "makeup-trends"},
    {slideName: "messyAndSexy",                           paneName: "makeup-trends"},
    {slideName: "sunKissed",                              paneName: "makeup-trends"},
    {slideName: "amazingFirsts",                          paneName: "maxFactorHeritage"},
    {slideName: "maxInnovator",                           paneName: "maxFactorHeritage"});
}


CarouselMgr.prototype.isKnownPaneName = function (paneName)
{
  var bFound = false;

  if (this.getPaneNdxByName (this.allPanes, paneName) != -1)
    bFound = true;

  if (bFound == false)
    if (this.getPaneNdxBySlideName (paneName) != -1)
      bFound = true;

  if (bFound == false)
    for (ndx = 0; ndx < this.contentNames.length; ndx++)
      if (this.contentNames[ndx] == paneName)
        bFound = true;

  if (bFound == false)
    if (paneName == "makeupAdvisor")
      bFound = true;

  return (bFound);
}


CarouselMgr.prototype.loadContent = function (pane)
{
  // content has to be loaded dynamically before we display it-
  // before making call to backend display a wait message
  jQuery("#waitPanel").show();

  // set a flag to ensure we only try a certain number of times
  this.loadAttempts = 0;

  setTimeout ("carouselMgr.loadContentNow('" + pane.id + "')", 200);
}


CarouselMgr.prototype.loadContentNow = function (id)
{
  var pane    = this.panes[this.getPaneNdxByName (this.panes, id)];

  jQuery.ajax ({url:      pane.url,
                dataType: "html",
                success:  function(html){carouselMgr.loadAjaxContent(html);}
              });
}


CarouselMgr.prototype.loadAjaxContent = function(html)
{
  var ndx    = this.getPaneNdxByPosition (0);
  var pane   = this.panes[ndx];

  jQuery("#" + pane.idContent).html(html);

  jQuery("#waitPanel").hide();
  pane.loaded = true;

  // update all the new *.do links to be carouselMgr.goToPane instead
  urlMgr.xlateLinksToAnchors ();

  this.showLoadedContent ();
}


// opacityIncrease
CarouselMgr.prototype.opacityIncrease = function (divName)
{
  //alert (divName);

  // TODO: can probably just call this.getPaneNdxByName and pass the ndx to the carousel
  carousel.opacityIncrease(divName);
}


// opacityRestore
CarouselMgr.prototype.opacityRestore = function (divName)
{
  carousel.opacityRestore(divName);
}


// reinitPanes
CarouselMgr.prototype.reinitPanes = function ()
{
  var ndx;

  // set every panel's position to -1
  for (ndx = 0; ndx < this.allPanes.length; ndx++)
    this.allPanes[ndx].positionNdx = -1;

  // carousel will set positions of the panes in it's pane array
  carousel.reinitPanes (this.panes);

  // panes with position == -1 are not going to be displayed so we can hide them  
  for (ndx = 0; ndx < this.allPanes.length; ndx++)
    if (this.allPanes[ndx].positionNdx == -1)
      jQuery("#"+this.allPanes[ndx].id).hide();
    else
      jQuery("#"+this.allPanes[ndx].id).show();
}


// rotateComplete
// this function is called after carousel.rotate does its thing and rotates the desired pane front and center
// we're now ready to display the content on the center pane -- make sure the content has been load first tho
CarouselMgr.prototype.rotateComplete = function ()
{
  var ndx    = this.getPaneNdxByPosition (0);
  var pane   = this.panes[ndx];

  if (pane.loaded)
  {
    this.loadAttempts = 0;
    this.goToPaneComplete();
  }
  else
  {
    // check to make sure pane is loaded- if not, then make ajax call to get the HTML content for this pane
    if (this.loadAttempts == 0)
      this.loadContent (pane);
  }
}


CarouselMgr.prototype.setAutoSlide = function (paneName, bOn)
{
  if ((document.location.hash.length == 0) || (getHash() == "makeup"))
    if (IE6 == false)
    {
      this.allPanes[this.getPaneNdxByName (this.allPanes, paneName)].bAutoSlide = bOn;
      if (bOn)
        this.timer = setTimeout("carouselMgr.autoSlide()", 12000);
    }
}


CarouselMgr.prototype.getNormalizedPaneName = function ()
{
  var paneName = this.panes[0].id;
  if (this.panes[0].childContentPanes != null)
     paneName = this.panes[0].childContentPanes[this.currentContent].contentName;

  return (paneName);
}


// showLoadedContent
// this function is called after carousel.rotate does its thing
// we're now ready to display the content on the center pane
CarouselMgr.prototype.showLoadedContent = function ()
{
    this.loadAttempts = 0;
    this.goToPaneComplete();
}


CarouselMgr.prototype.doSlidePane = function(bGoDirectlyToSlide)
{
  var pane      = this.panes[0];
  var slides    = pane.slides;
  var paneName;
  var next;

  if ((slides != null) && (pane.nextSlideName != ""))
  {
    if (pane.id == pane.nextSlideName)
      next = 0;
    else
      next = this.getSlideNdxBySlideName (pane.nextSlideName, pane);

    this.slidePane(next, bGoDirectlyToSlide);
    pane.nextSlideName = "";
  }
  else
  {
    paneName = this.getNormalizedPaneName ();
    if (slides != null)
    {
      if (slides.currentSlide != 0)
        paneName = slides.slideData[slides.currentSlide].slideName;
      this.runSlideInit ();
    }

    this.currentPane        = paneName;
    setHash (paneName);

    // re-enable url change detection logic
    urlMgr.enableUrlDetection ();
    //urlMgr.urlDetectEnabled = true;
  }

  carouselMgr.timer = setTimeout("carouselMgr.autoSlide()", 12000);
}


CarouselMgr.prototype.slidePane = function(next, bGoDirectlyToSlide)
{
  var slides     = this.panes[0].slides;
  var currentDiv = slides.slideData[slides.currentSlide].slideName;
  var nextDiv    = slides.slideData[next].slideName;

  slides.currentSlide = next;

  if (bGoDirectlyToSlide)
  {
    jQuery("#" + currentDiv).css({left:"816px", opacity:0.0});
    jQuery("#" + nextDiv   ).css({left:"0px",   opacity:1.0});

    this.setHash();
    this.runSlideInit();
  }
  else
  if (slides.currentSlide < next)
  {
    slides.currentSlide = next;
    jQuery("#" + currentDiv)                      .animate ({left:"-816px", opacity:0.0}, 800);
    jQuery("#" + nextDiv   ).css("left", "816px") .animate ({left:"0px",    opacity:1.0}, 800, "linear", function(){carouselMgr.setHash();carouselMgr.runSlideInit();});
  }
  else
  {
    slides.currentSlide = next;
    jQuery("#" + currentDiv).css("left", "0px"   ).animate ({left:"816px",  opacity:0.0}, 800);
    jQuery("#" + nextDiv   ).css("left", "-816px").animate ({left:"0px",    opacity:1.0}, 800, "linear", function(){carouselMgr.setHash();carouselMgr.runSlideInit();});
  }

  jQuery("#sliderPagination").fadeOut("slow", function(){carouselMgr.displayContent();});
}


CarouselMgr.prototype.runSlideInit = function ()
{
  var slides = this.panes[0].slides;
  if (slides)
  {
    var initFunction = slides.slideData[slides.currentSlide].initFunction;
    if (initFunction != "")
      eval(initFunction);
  }
}


CarouselMgr.prototype.setHash = function ()
{
  var slides   = this.panes[0].slides;
  var paneName;
  if (slides != null)
  {
    paneName   = (slides.currentSlide == 0) ? this.panes[0].id : slides.slideData[slides.currentSlide].slideName;

    this.currentPane = paneName;
    setHash(paneName);
  }

  // re-enable url change detection logic
  urlMgr.enableUrlDetection ();
  //urlMgr.urlDetectEnabled = true;
}


CarouselMgr.prototype.slidesAdd = function (paneName, hiliteColor, arrowName, slideData)
{
  // add the slides data to the pane object
  var pane    = this.allPanes[this.getPaneNdxByName (this.allPanes, paneName)];
  pane.slides = new Slides (hiliteColor, slideData);

  // ensure the first slide's left position is 0
  jQuery("#" + slideData[0].slideName).css("left", 0).css("top", 0);

  // all but the first slide should be off to the right so they can slide into place from the right
  for (ndx = 1; ndx < slideData.length; ndx++)
    jQuery("#" + slideData[ndx].slideName).css("left", 816).css("top", 0).css("opacity", 0.0);

  pane.slides.arrowImage = "/images/carousel/pagination/" + arrowName;
}

