var imagesArray = [];
var onStartRotate = function(){};
var isOnStartRotateDone = false;
var pixelPerStep = 50;
var imageWidth = 710;
var IMAGE_LOAD_DELAY_TIME = 0;
var rotateOnLoadDone = false;

var readyForAborting = false;

var currentImageIndex = 0;
var startXCoord = 0;

var destinationImageIndex = 0;
var rotationSteps = 0;
var destinationTime = 0;
var rotationTimer = null;
var rotationAscending = true;

var isUserRotating = 0;

function pageLoaded()
{
  readyForAborting = true;
}

function initImages(imageArrayParam)
{
  if (readyForAborting && !document.all)
  {
    window.stop();
  }
  document.getElementById('rotationHolder').onmousedown = null;

  document.onmouseup = stopRotate;
  imagesArray = imageArrayParam;
  imagesProcessed = 0;
  pixelPerStep = imageWidth / imagesArray.length / 2;
  document.getElementById('imageHolder').innerHTML = '';

  initRotationStep(0);
  lastImageUpdate = new Date().getTime();
  window.setTimeout("initRemainingRotationSteps(" + lastImageUpdate +")", IMAGE_LOAD_DELAY_TIME);
}

function initRemainingRotationSteps(lastKnownUpdate)
{
  if (lastImageUpdate <= lastKnownUpdate)
  {
    for (var i = 1; i < imagesArray.length; i++)
    {
      initRotationStep(i);
    }
  }
}

function initRotationStep(stepIndex)
{
  var imgTag = document.createElement('img');
  imgTag.onload = imageLoaded;
  imgTag.onerror = imageNotLoaded;
  var index = (currentImageIndex + stepIndex) % imagesArray.length;

  imgTag.src = imagesArray[index];
  imgTag.id = getIdForImageIndex(index);
  imgTag.style.display = index == currentImageIndex ? 'block' : 'none';
  imgTag.alt = '';
  document.getElementById('imageHolder').appendChild(imgTag);
}

var imageNotLoaded = function(evt)
{
 evt = evt || window.event;
 var targetObj = evt.target;
 var sourceImage = targetObj != null ? evt.target.src : '';
 return false;
};

var imageLoaded = function(evt)
{
 evt = evt || window.event;
 var targetObj = evt.target;
 var sourceImage = targetObj != null ? evt.target.src : '';
 imageProcessed(sourceImage, '+');
 return false;
};

function imageProcessed(imageURL, status)
{
  imagesProcessed++;
  if (imagesProcessed == imagesArray.length)
  {
    if(!rotateOnLoadDone)
    {
      rotateOnLoadDone = true;
      rotateToImage(25);
    }
  }
  else
  {
    document.getElementById('rotationHolder').onmousedown = startRotate;
  }
}

var startRotate = function(event)
{
  rotateOnLoadDone = true; // disable automatically rotate to the start position
  if(rotationTimer != null)
  {
    stopRotationTimer();
  }
  isUserRotating = 1;
  if (!event) event = window.event;

  if (event.button == 0 || document.all && event.button == 1)
  {
    onStartRotateDone = false;
    document.onmousemove = handleMovement;
    startXCoord = event.clientX;
    return false;
  }
};

var stopRotate = function(event)
{
  if (isUserRotating == 1)
  {
    isUserRotating = 0;
    if (!event) event = window.event;
    if (event.button == 0 || document.all && event.button == 1)
    {
      document.onmousemove = null;
      return false;
    }
  }
};

var handleMovement = function(event)
{
  if (!event) event = window.event;

  var newXCoord = event.clientX;

  var newIndex = getNewIndex(newXCoord);
  if (newIndex != currentImageIndex)
  {
    if(!onStartRotateDone)
    {
      onStartRotate();
      onStartRotateDone = true;
    }
    displayImageIndex(newIndex);
    startXCoord = newXCoord;
  }
  return false;
};

function getNewIndex(newXCoord)
{
  if (imagesArray.length == 0)
  {
    return 0;
  }

  var delta = (startXCoord - newXCoord) / pixelPerStep;

  if (delta > 0)
  {
    delta = Math.floor(delta);
  }
  else
  {
    delta = Math.ceil(delta);
  }
  var newIndex = currentImageIndex - delta;

  if (newIndex < 0)
  {
    newIndex = (newIndex % imagesArray.length) + imagesArray.length;
  }
  if (newIndex >= imagesArray.length)
  {
    newIndex = newIndex % imagesArray.length;
  }
  return newIndex;
}

function displayImageIndex(imgIndex)
{
  blockImage(currentImageIndex);
  currentImageIndex = imgIndex;
  showImage(currentImageIndex);
}

function getIdForImageIndex(index)
{
  return 'image' + index;
}

function blockImage(imgIndex)
{
  var element = document.getElementById(getIdForImageIndex(imgIndex));
  if (element != null)
  {
    element.style.display = 'none';
  }
}

function showImage(imgIndex)
{
  var element = document.getElementById(getIdForImageIndex(imgIndex));
  if(element != null)
  {
    element.style.display = 'block';
  }
}

function rotateToImage(imgIndex)
{
  if(imgIndex == currentImageIndex)
  {
    return; // do nothing
  }
  // decide ascending or descending rotation
  var leftDistance = (imgIndex >= currentImageIndex)
    ? imgIndex - currentImageIndex : imagesArray.length - imgIndex - currentImageIndex;
  var rightDistance = (currentImageIndex >= imgIndex)
    ? currentImageIndex - imgIndex : imagesArray.length - imgIndex - currentImageIndex;
  rotationAscending = leftDistance > rightDistance; // > means long distance, < means short distance
  rotationSteps = Math.abs(imgIndex - currentImageIndex);
  destinationImageIndex = imgIndex;
  startRotationTimer();
}

function startRotationTimer()
{
  destinationTime = (new Date()).getTime() + 600;
  stopRotationTimer();
  rotationTimer = setInterval("doRotate()", 20);
}

function stopRotationTimer()
{
  try{
  clearInterval(rotationTimer);
  }catch(ignore){}
}

function doRotate()
{
  var remainingTime = destinationTime - (new Date()).getTime();
  if(remainingTime <= 0 || currentImageIndex == destinationImageIndex)
  {
    stopRotationTimer();
    displayImageIndex(destinationImageIndex);
  }
  else
  {
    var diff = Math.abs(destinationImageIndex - currentImageIndex);
    var percentage = 1 / 600 * remainingTime;
    var factor = Math.sin(Math.PI * percentage) / 6;
    diff = Math.ceil(diff * factor);
    if(rotationAscending)
    {
      displayImageIndex((currentImageIndex + diff) % imagesArray.length);
    }
    else
    {
      displayImageIndex((currentImageIndex - diff + imagesArray.length) % imagesArray.length);
    }
  }
}

