//Constants used exterbally
var POPULATEGRID_RANDOM_IMAGE = -1;

//Internal variables
var _ImagesWithAttribution = [];
var _AttributionLinks =[];


function AddAttributionLinks()
{
   for(var i = 0; i < _ImagesWithAttribution.length; i++) {
      var img =  _ImagesWithAttribution[i];
      var link = document.createElement('A');

      link.href=img.attribUrl;
      
      img.style.borderStyle='none';
      img.style.borderWidth='0px';

      //Add the link before the picture
      var cont = img.parentNode;
      
      //Move the picture into the link
      cont.insertBefore( link , img );
      cont.removeChild(img);
      link.appendChild(img);
      
      _AttributionLinks.push(link);
   }
}

function RemoveAttributionLinks()
{
   while(_AttributionLinks.length > 0) {
      var link =  _AttributionLinks[0];
      var img =  link.firstChild;

      var cont = link.parentNode;
      
      link.removeChild(img);
      cont.insertBefore( img, link);
      cont.removeChild(link);      
      
      //remove the first element from the array of links
      _AttributionLinks.shift();
   }
}

function AddImage(cont,imgdata)
{
   var newimg = document.createElement('IMG');
   newimg.src = imgdata.src;
   newimg.origWidth = imgdata.width;
   newimg.origHeight = imgdata.height;
   newimg.className = "gridimage";
   newimg.title = GetImageTitle(imgdata);

   //Is there audio to play?
   if(imgdata.audio) {
      newimg.audioElem = document.getElementById(imgdata.audio);
      if(newimg.audioElem) {
         newimg.onclick=function(){
            if( Options.sounds && Options.canPlaySounds) {
               var now = new Date();
               if(     this.lastPlayed 
                  && ((now.getTime() - this.lastPlayed.getTime()) < 500)) {
                  //It's been less than 500 millisecs since we last played. Abort;
                  return;
               }
               this.lastPlayed = now;
               this.audioElem.play();
            }
         }
      } 
   }

   //should this image be draggable?
   if(imgdata.dragItem) {
      newimg.onload=function(){MakeDraggable(newimg, imgdata.dragItem);};
   }
   if(imgdata.dragTargetFor) {
      newimg.onload=function(){MakeDragTarget(newimg,imgdata.dragTargetFor);};
   }
   
   if(imgdata.url) {
      newimg.attribUrl = imgdata.url;
      _ImagesWithAttribution.push(newimg);
   }
   cont.appendChild(newimg);
}


function GetImageTitle(imgdata)
{
   var title = '';
   if( imgdata.name ) {
      title += imgdata.name; 
   }
   
   if( imgdata.author || imgdata.url ) {
      if(title != '') {
         title += ' ('; 
      } else {
         title += '('; 
      }
   }
   if( imgdata.author ) {
      title += 'Photo by '+imgdata.author; 
   }
   if( imgdata.url ) {
      if( imgdata.author ) { 
         title += '. '; 
      }
      title += 'Details at '+imgdata.url; 
   }
   if( imgdata.author || imgdata.url ) {
      title += ')';   
   }
   return title;
}


function IsArray(totest){
   return typeof(totest)=='object'&&(totest instanceof Array);
}

//Shuffle algorithm from http://sedition.com/perl/javascript-fy.html
function FisherYatesShuffle ( myArray ) {
  var i = myArray.length;
  if ( i == 0 ) return false;
  while ( --i ) {
     var j = Math.floor( Math.random() * ( i + 1 ) );
     var tempi = myArray[i];
     var tempj = myArray[j];
     myArray[i] = tempj;
     myArray[j] = tempi;
   }
}

//divid = id of div to place grid of images in
//images = data about images to place in grid
//shuffle = shuffle the order of images in the grid
//imgIndex = if there are multiple images for a spot in the grid, 
//             which image should be used or POPULATEGRID_RANDOM_IMAGE 
//             for a random image 
function PopulateGrid(divid, images, shuffle, imgIndex)
{
   var div = document.getElementById(divid);
   div.innerHTML="";
   
   if( IsArray(images) ) {
      var imgarray;
      
      if(shuffle) {
         //copy the array
         var imgarray = images.slice(0);
         FisherYatesShuffle(imgarray);
      } else {
         imgarray = images;
      }
      
      for(var i = 0; i < imgarray.length; i++) {
         //Each item in the image array is another array
         //At the moment, only used for letters where in the inner array
         // 0 = lowercase, 1 =uppercase
         var itemarray = imgarray[i];
         var chosenIndex;

         if(imgIndex == POPULATEGRID_RANDOM_IMAGE) {
            chosenIndex = Math.floor(Math.random()*(1+itemarray.length));
         } else {
            chosenIndex = imgIndex;
         }
         AddImage(div,itemarray[chosenIndex]);
      }
   } else { 
      var imgarray  = [];
      
      //First populate an array - one image for each spot in grid
      for (var key in images) {
         var imgdataarray = images[key];
         var chosenIndex;
         
         if(imgIndex == POPULATEGRID_RANDOM_IMAGE) {
            chosenIndex = Math.floor(Math.random()*(1+imgdatamarray.length));
         } else {
            chosenIndex = imgIndex;
         }
         imgarray.push([key, imgdataarray[chosenIndex]]);
      }
      
      //Order the array as we want
      if(shuffle) {
         FisherYatesShuffle(imgarray);
      } else {
         //Create a sorted array     
         imgarray.sort(function(a, b) {return a[0] - b[0]});
      }
      //Add the images to the grid
      for(var i = 0; i < imgarray.length; i++) {
         AddImage(div,imgarray[i][1]);
      }
   }
  
   ResizeGrid(divid);
}

function ResizeGrid(divid)
{
   var div = document.getElementById(divid);
   
   //try rows starting with 3
   var numrows = 3;
   var actualrows = 0;
   var lastnumrows = 0;
   var growing = null ; //whether we are growing numrows or shrinking it - used to detect yoyoing 
   
   while(   numrows > 1 
         && numrows < 5 )
   {
//      alert('Trying numrows: '+numrows);
      totalwidth = ResizeGridRows(div, false, numrows);
      actualrows = Math.ceil(totalwidth/div.offsetWidth);
      
      if( actualrows == numrows ) {
         break;
      }
      else if( actualrows > numrows ) {
         if( growing == null) {
            growing = true; //we are going to grow the number of rows
         } else if(growing == false) {
            //we were shrinking but now we want to grow... use the bigger number of rows we are yoyoing around
            numrows++;
            break;
         }
         numrows++;
      }
      else { //  actualrows < numrows
         if( growing == null) {
            growing = false; //we are going to reduce the number of rows
         } else if(growing == true) {
            //we were growing but now we want to shrink... use the bigger number of rows we are yoyoing around
            break;
         }

         numrows--;
      }
//      alert('totalwidth: '+totalwidth+' actualrows: '+actualrows+' so new numrows: '+numrows);
   }
   ResizeGridRows(div, true, numrows);
}

//If show is true it resizes all the images to the right size
//otherwise it calculates the total width (including margin) for what the scaled images would take up
function ResizeGridRows(div, show, numrows) 
{
   //We use the style height rather than the offsetheight as if we are resizing to a smaller window we
   //we change the style height but the offsetheight won't change until the contentrs are shrunk to fit
   var contheight = parseInt(div.style.height);

   var margintopfraction = 0.02;  //fraction of div used as margin above each row
   var imgheightfraction = (0.96 - (margintopfraction * numrows)) / numrows; //fraction of div used for each image
   var marginsidefraction    = 0.01;
   
   var imgheight_forscreen = contheight * imgheightfraction;
   var totalwidth = 0;

   if (div && div.hasChildNodes()) {
      var children = div.childNodes;

      for(var i = 0; i < children.length; i++) {
         //careful not to count the ticks in the resizing algorithm
         if( children[i].tagName == 'IMG' &&  children[i].className == "gridimage") {
            //ensure the height isn't too small (or large) so the img will look 
            //strange when scaled
            var imgheight = imgheight_forscreen;
            var imgwidth;

            if(imgheight_forscreen < children[i].origHeight / 4) {
               imgheight = children[i].origHeight / 4;
            }
            if(imgheight_forscreen > children[i].origHeight * 2) {
               imgheight = children[i].origHeight * 2;
            }
            //work out the width that maintains the aspect ratio
            imgwidth = children[i].origWidth * (imgheight / children[i].origHeight);
         
            if(show) {
               children[i].width  =  Math.floor(imgwidth);
               children[i].height =  Math.floor(imgheight);
               children[i].style.marginTop    = Math.floor(contheight * margintopfraction)+'px';
               children[i].style.marginBottom = '0px';
               children[i].style.marginLeft   = Math.floor(div.offsetWidth * marginsidefraction)+'px';
               children[i].style.marginRight  = Math.floor(div.offsetWidth * marginsidefraction)+'px';
               children[i].style.padding = '0px';
            } else {
               totalwidth += imgwidth + 2*Math.floor(div.offsetWidth * marginsidefraction);
            }
         }
      }
   }
   if( !show ) {
      return totalwidth;
   }
}
