/**
* Usage examples:
*   Usage: var gallery = new Gallery('gallery', 'file1.jpg:file2.jpg:file3.jpg');
*   Usage: var gallery = new Gallery('gallery', 'file1.jpg:file2.jpg:file3.jpg', 800, 600, 800, 200);
*   Usage: var gallery = new Gallery('gallery', 'file1.jpg:file2.jpg:file3.jpg', { largeDivWidth: 800, largeDivHeight: 600, smallDivWidth: 800, smallDivHeight: 200 });
*   Usage: var gallery = new Gallery('gallery', 'file1.jpg:file2.jpg:file3.jpg', { largeDivWidth: 800});
*   Usage: var gallery = new Gallery({ src: 'file1.jpg', srcPreview: 'filesmall1.jpg', title: 'file', alt: 'file' }); 
*   src - Изображение большого разрешения
*   srcPreview - Превью, например, сгенерированное скриптом
*   title - Подпись изображения
**/

// gallery - id элемента(div) в котором расположится галерея
// files - список файлов для отображения
// largeDivWidth, largeDivHeight - величина div для изображения
// smallDivWidth, smallDivHeight - величина div для экскизов

function Gallery(gallery, files, largeDivWidth, largeDivHeight, smallDivWidth, smallDivHeight)
{
  if(typeof gallery == 'string' && gallery.length) 
  {
    gallery = document.getElementById(gallery);
    this.gallery = gallery;
  }
  else
  {
    throw Object("Error: argument 'gallery' not exists.");
  }
  
  var currentGallery = this;
  
  var images = new Array();
  
  if(typeof files == 'string' && files.length)
  {
    // Для совместимости с предыдущей версией
  
    var separator = ':'; // Разделитель имен файлов
    
    files = files.replace(/^[:\s]+|[:\s]+$/g, '').split(separator);
	
    for(var i = 0; i < files.length; i++)
    {
      var image = files[i];
      images.push( { src: image, srcPreview: image, title: '', alt: image } );
    }
  }
  else if(files instanceof Array)
  {
    
    for(var i = 0; i < files.length; i++)
    {
      	
      var image = files[i];
	  
      if(typeof image == 'object' && image.src)
      {
	    
        if(!image.srcPreview)
        {
          image.srcPreview = image.src;
        }
		
        if(!image.title)
        {
          image.title = '';
        }

        if(!image.alt)
        {
          image.alt = image.src;
        }
		
        images.push(image);
      }
      else if(typeof image == 'string')
      {
        images.push( { src: image, srcPreview: image, title: '', alt: image } );
      }
	  
    }
  }
  else
  {
    throw Object("Error: argument 'files' not exists.");
  }

  if(!images.length) throw Object("Error: no images to show.");
  
  if(typeof largeDivWidth == 'object')
  {
    var wh = largeDivWidth;
	
    largeDivWidth = wh.largeDivWidth;
    largeDivHeight = wh.largeDivHeight;
    smallDivWidth = wh.smallDivWidth;
    smallDivHeight = wh.smallDivHeight;
  }

  largeDivWidth = largeDivWidth || Gallery.LargeDivWidth;
  largeDivHeight = largeDivHeight || Gallery.LargeDivHeight;
  
  smallDivWidth = smallDivWidth || Gallery.SmallDivWidth;
  smallDivHeight = smallDivHeight || Gallery.SmallDivHeight;
  
  var largeDiv = document.createElement('div');
  largeDiv.className = Gallery.LargeDivClassName;
  largeDiv.style.width = largeDivWidth + 'px';
  largeDiv.style.height = largeDivHeight + 'px';

  var loaded = 0; // Количество загруженных изображений
  var maxImages = images.length;
  
  var info = document.createElement('div');
  info.className = Gallery.InfoDivClassName;
  
  var maxTitleWidth = smallDivWidth > largeDivWidth ? smallDivWidth : largeDivWidth;
  info.style.width = maxTitleWidth + 'px';
  info.innerHTML = Gallery.cutText("Загружено " + loaded + " из " + maxImages, maxTitleWidth);
  
  var infoBox = document.createElement('div');
  infoBox.className = Gallery.InfoBoxDivClassName;

  if(window.attachEvent)
  {
    window.attachEvent("onload", function() { document.body.appendChild(infoBox) });
  }
  else if(window.addEventListener)
  {
    window.addEventListener("load", function() { document.body.appendChild(infoBox) }, false);
  }
  
  info.onmouseover = function(e) 
  {
    if(smallDiv.active && smallDiv.active.title) 
    {
      info.onmousemove = function(e)
      {
        var coords = Gallery.getMouseXY(e);
        infoBox.style.left = coords.x + 1 + 'px'; 
	infoBox.style.top = coords.y + 1 + 'px';
      }
            
      infoBox.style.display = 'block';
      infoBox.innerHTML = smallDiv.active.title;
    }
  }
  
  info.onmouseout = function() 
  {
    infoBox.style.display = 'none'; 
  }

  var smallDiv = document.createElement('div');
  smallDiv.className = Gallery.SmallDivClassName;
  smallDiv.style.width = smallDivWidth + 'px';
  smallDiv.style.height = smallDivHeight + 'px';
  
  gallery.appendChild(largeDiv);
  gallery.appendChild(info);
  gallery.appendChild(smallDiv);
  
  this.smallDiv = smallDiv;
  this.largeDiv = largeDiv;
  
  for(var i = 0; i < images.length; i++)
  {
    var img = new Image();
    img.style.display = 'none';
    smallDiv.appendChild(img);

    if(img.attachEvent)
    {
      img.attachEvent("onload", imageOnLoad );
      img.attachEvent("onload", imageOnLoadCount);
      img.attachEvent("onerror", imageOnError);
      img.attachEvent("onabort", imageOnError);
    }
    else if(img.addEventListener)
    {
      img.addEventListener("load", imageOnLoad, false);
      img.addEventListener("load", imageOnLoadCount, false);
      img.addEventListener("error", imageOnError, false);
      img.addEventListener("abort", imageOnError, false);
    }
    
    img.srcFull = images[i].src;
    img.title = images[i].title;
    img.alt = images[i].alt;
    img.src = images[i].srcPreview;
  } 
  
  img = null; // Убираем утечки IE
  
  function imageOnError(e)
  {
    var element = e.target || window.event.srcElement; // Элемент img в котором произошло событие   
    imageOnLoadCount(element, true);
  }
  
  function imageOnLoadCount(element, error)
  {     
    if(!error)
    {
      loaded++;
    }
    else
    {
      maxImages--;
      smallDiv.removeChild(element);
    }
    
    info.innerHTML = Gallery.cutText("Загружено " + loaded + " из " + maxImages, maxTitleWidth);

    if(loaded == maxImages)
    {
      smallDiv.style.background = '#fff';
      largeDiv.style.background = '#fff';
      info.innerHTML = Gallery.cutText(smallDiv.active ? smallDiv.active.title : smallDiv.firstChild.title, maxTitleWidth);
    }
  }
  
  function imageOnLoad(e)
  {
    var element = e.target || window.event.srcElement; // Элемент img в котором произошло событие

    var size = Gallery.getSize(element.width, 0, element.height, smallDivHeight - Gallery.SmallDivPaddingHeight);
	 
    element.style.width = size.width + 'px';
    element.style.height = size.height + 'px';
	
    if(!loaded)
    {
      smallDiv.style.background = '#fff';
    }

    element.style.display = '';
	
    element.onclick = imageOnClick;
   
    if(smallDiv.firstChild == element && !smallDiv.active)
    {
      element.onclick();
    }
    
  }
  
  function imageOnClick()
  { 
    //largeDiv.removeChild(largeImage);  
    
    var largeImage = new Image();
	
    var current = this;
		
    largeImage.onload = function()
    {
      largeImage = null; // Утечки IE
	
      var size = Gallery.getSize(this.width, largeDivWidth, this.height, largeDivHeight); // Получаем допустимый размер изображения  
	  
      this.style.width = size.width + 'px';
      this.style.height = size.height + 'px';
	  
      // Помещаем изображение в центр
      this.style.left = (largeDivWidth - size.width) / 2 + 'px';
      this.style.top = (largeDivHeight - size.height) / 2 + 'px';
	  
      this.title = current.title;
      this.alt = current.alt;
      
      this.oncontextmenu = function() { return false; }
	  
      this.onmousedown = function(e)
      {
        if(e)
        {
          if(0 == e.button) currentGallery.next();
          else if(2 == e.button) currentGallery.prev();
        }
        else if(window.event)
        {
          if(1 == window.event.button) currentGallery.next();
          else if(2 == window.event.button) currentGallery.prev(); 
        }
      }
	  
      if(smallDiv.active)
      {
        smallDiv.active.style.border = '3px solid #fff';
      }
      
      if(largeDiv.firstChild)
      {
        largeDiv.replaceChild(this, largeDiv.firstChild);
      }
      else
      {
        largeDiv.appendChild(this);
      }	  
	  
      if(loaded == maxImages)
      {
        info.innerHTML = Gallery.cutText(this.title, maxTitleWidth);
      }
	  
      smallDiv.active = current;
	
      current.style.border = Gallery.BorderStyle;
    }
	
    largeImage.src = current.srcFull;
  }
}

// Некоторые стандартные параметры галереи

Gallery.LargeDivClassName = 'galleryLargeDiv';
Gallery.LargeDivWidth = 452;
Gallery.LargeDivHeight = 339;

Gallery.SmallDivClassName = 'gallerySmallDiv';
Gallery.SmallDivWidth = 652;
Gallery.SmallDivHeight = 150;

Gallery.InfoDivClassName = 'galleryInfoDiv';
Gallery.InfoBoxDivClassName = 'galleryInfoBoxDiv';

Gallery.BorderStyle = '3px solid #8e8e8e';
// Gallery.SmallDivPaddingWidth = 0;
Gallery.SmallDivPaddingHeight = 40; 
Gallery.ScrollPadding = 5;

// Метод обрезает текст под конкретный размер элемента и добавляет '...' 
Gallery.cutText = function(text, maxWidth)
{
  
  var letter = document.createElement('span');
  letter.style.visibility = 'hidden';
  letter.style.position = 'absolute'; 
  letter.innerHTML = text;
  document.body.appendChild(letter); 
  
  if(letter.offsetWidth > maxWidth)
  {
    var length = 0;
    do
    {
      length++;
      letter.innerHTML = text.substr(0, length) + '...';    
    } 
    while(letter.offsetWidth < maxWidth);
    
    text = text.substr(0, length - 1) + '...';
  }
  
  document.body.removeChild(letter);
  
  return text;

}

// Метод определяет координаты мыши
Gallery.getMouseXY = function(e)
{
  var x = 0, y = 0;

  if (!e) e = window.event;

  if (e.pageX || e.pageY)
  {
    x = e.pageX;
    y = e.pageY;
  }
  else if (e.clientX || e.clientY)
  {
    x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
    y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
  }

  return { "x": x, "y": y };
}

// Метод масштабирует изображение под конкретные размеры
// Если maxWidth == 0 или maxHeight == 0, то в этом направлении масштабирования не будет
Gallery.getSize = function(width, maxWidth, height, maxHeight)
{
  
  if(maxWidth && width > maxWidth)
  {
    var k = width / height; // Коэффициент пропорциональности сторон изображения
    var diff = width - maxWidth;
	
    width = maxWidth;
    height = height - diff / k;
  }
	
  if(maxHeight && height > maxHeight)
  {
    var k = height / width; // Коэффициент пропорциональности сторон изображения
    var diff = height - maxHeight;
	  
    height = maxHeight;
    width = width - diff / k;
  }
  
  return { width: width, height: height };
}

// IE5
if(!Array.prototype.push)
{
  Array.prototype.push = function(element) 
  {
    this[this.length] = element;
  }
}

Gallery.prototype.next = function() 
{
  var smallDiv = this.smallDiv;
  
  if(!smallDiv.active) return;
  
  var nextImg = smallDiv.active;
  
  do
  {
    if(nextImg == smallDiv.lastChild)
    {
      nextImg = smallDiv.firstChild;  
    }
    else
    {
      nextImg = nextImg.nextSibling;
    }
  } while(!(nextImg && nextImg.complete));

  nextImg.onclick();

  smallDiv.scrollLeft = nextImg.offsetLeft - Gallery.ScrollPadding;
}

Gallery.prototype.prev = function() 
{ 
  var smallDiv = this.smallDiv;
  
  if(!smallDiv.active) return;
  
  var prevImg = smallDiv.active;

  do
  {
    if(prevImg == smallDiv.firstChild)
    {
      prevImg = smallDiv.lastChild;  
    }
    else
    {
      prevImg = prevImg.previousSibling;
    }
  } while(!(prevImg && prevImg.complete));

  prevImg.onclick();
  
  smallDiv.scrollLeft = prevImg.offsetLeft - Gallery.ScrollPadding;
}
