﻿// FILE Navigation.js
// Contains methods used to navigate the content


var g_navigationManager = new NavigationManager();

function NavigationManager()
{

   if (typeof (NavigationManager._initialized) == 'undefined')
   {
      NavigationManager.prototype.StartScrollTo = StartScrollTo;
      NavigationManager.prototype.ChangeScrollPosition = ChangeScrollPosition;
      NavigationManager.prototype.GetTheScrollPositionInFirstTimeRange = GetTheScrollPositionInFirstTimeRange;
      NavigationManager.prototype.GetTheScrollPositionInSecondTimeRange = GetTheScrollPositionInSecondTimeRange;
      NavigationManager.prototype.GetTheScrollPositionInThirdTimeRange = GetTheScrollPositionInThirdTimeRange;
      NavigationManager.prototype.ScrollTo = ScrollTo;

      NavigationManager.prototype.ClearTimerInterval = ClearTimerInterval;
   }
   NavigationManager._initialized = true;

   this.scrollInterval = null;
   this.initialScrollPosition = 0;
   this.finalScrollPosition = 0;
   this.initialTime = null;

   this.c_totalScrollTimeMilisec = 1000;


   function StartScrollTo(elementNameToJumpTo)
   {
      var detailsScrollerArea = document.getElementById("detailsScrollerArea");
      var elementToJumpTo = document.getElementById(elementNameToJumpTo);
      if (elementToJumpTo == null)
      {
         // This must be a bug probably in one of the XSL files.
         // TODO: send a bug report when that service becomes available.
         return;
      }

      this.initialScrollPosition = detailsScrollerArea.scrollTop;
      this.finalScrollPosition = elementToJumpTo.offsetTop;

      var topMaxScrolPosition = detailsScrollerArea.scrollHeight - detailsScrollerArea.clientHeight;
      if (this.finalScrollPosition > topMaxScrolPosition) this.finalScrollPosition = topMaxScrolPosition;
      
      this.initialTime = new Date();

      // In case we already have an active auto-scroll interval set we'll clear it.
      this.ClearTimerInterval();

      this.scrollInterval = setInterval("ChangeScrollPosition();", 20);
   }

   function ChangeScrollPosition()
   {
      var crtDate = new Date();

      var timeSpannMilisec = crtDate.getTime() - this.initialTime.getTime();

      // The scroll position will be set according to these rules:
      // In the first third of the scroll time
      //    We speed up with constant acceleration starting from zero speed.
      //    At the end of this interval we reach the maximum speed.
      // In the second third of the scroll time we move with constant speed which is the the maximum speed.
      // In the last third of the scroll time we lower the speed with a constant negative acceleration.
      //    At the end of this interval we reach the final position and zero speed.

      if (timeSpannMilisec < this.c_totalScrollTimeMilisec / 3)
      {
         curentScrollPosition = this.GetTheScrollPositionInFirstTimeRange(timeSpannMilisec);
      }
      else if (timeSpannMilisec < 2 * this.c_totalScrollTimeMilisec / 3)
      {
         curentScrollPosition = this.GetTheScrollPositionInSecondTimeRange(timeSpannMilisec);
      }
      else if (timeSpannMilisec < this.c_totalScrollTimeMilisec)
      {
         curentScrollPosition = this.GetTheScrollPositionInThirdTimeRange(timeSpannMilisec);
      }
      else
      {
         this.ClearTimerInterval();
         curentScrollPosition = this.finalScrollPosition;
      }

      this.ScrollTo(curentScrollPosition);
   }


   function GetTheScrollPositionInFirstTimeRange(timeSpannMilisec)
   {
      var totalScrollDistance = this.finalScrollPosition - this.initialScrollPosition;

      var a = this.initialScrollPosition;
      var c = (9 * totalScrollDistance) / (5 * this.c_totalScrollTimeMilisec * this.c_totalScrollTimeMilisec);
      var dt = timeSpannMilisec;
      var dt2 = dt * dt;

      return a + c * dt2;
   }

   function GetTheScrollPositionInSecondTimeRange(timeSpannMilisec)
   {
      var totalScrollDistance = this.finalScrollPosition - this.initialScrollPosition;

      var a = this.initialScrollPosition + totalScrollDistance / 5;
      var b = 6 * totalScrollDistance / (5 * this.c_totalScrollTimeMilisec);
      var c = 9 * totalScrollDistance / (5 * this.c_totalScrollTimeMilisec * this.c_totalScrollTimeMilisec);

      var dt = timeSpannMilisec - (this.c_totalScrollTimeMilisec / 3);
      var dt2 = dt * dt;

      return a + b * dt + c * dt2;
   }

   function GetTheScrollPositionInThirdTimeRange(timeSpannMilisec)
   {
      var totalScrollDistance = this.finalScrollPosition - this.initialScrollPosition;

      var a = this.initialScrollPosition + (4 * totalScrollDistance / 5);
      var b = 6 * totalScrollDistance / (5 * this.c_totalScrollTimeMilisec);
      var c = -(9 * totalScrollDistance / (5 * this.c_totalScrollTimeMilisec * this.c_totalScrollTimeMilisec));

      var dt = timeSpannMilisec - (2 * this.c_totalScrollTimeMilisec / 3);
      var dt2 = dt * dt;

      return a + b * dt + c * dt2;
   }


   function ScrollTo(scrollPosition)
   {
      var detailsScrollerArea = document.getElementById("detailsScrollerArea");
      detailsScrollerArea.scrollTop = scrollPosition;
   }

   function ClearTimerInterval()
   {
      if (this.scrollInterval != null)
      {
         clearInterval(this.scrollInterval);
         this.scrollInterval = null;
      }
   }
}


function ClickNavigationLink(elementNameToJumpTo)
{
   g_navigationManager.StartScrollTo(elementNameToJumpTo)
}

function ChangeScrollPosition()
{
   g_navigationManager.ChangeScrollPosition();
}
