//$Id: gallerix.js,v 1.10 2008/07/28 01:48:28 silviogutierrez Exp $


//Gallerix Namespace
var Gallerix = Gallerix || {};
Gallerix.fn = Gallerix.fn || {};
Gallerix.settings = Gallerix.settings || {};
Gallerix.cache = Gallerix.cache || {};


$(document).ready(function() {  
  
  Gallerix.init();
  
  var pid = Gallerix.pid;
  
  // Finalize the loading process using the preloaded image.
  Gallerix.cycle.image = Gallerix.settings.currentData;
  Gallerix.finalize();

  if (Gallerix.settings.mode == 'grid' && pid) {
    Gallerix.switchModes();
    Gallerix.fetch(Gallerix.settings.fetchURL + pid, false, false);
    window.location.hash = "#" + pid;        
  }  
  else if (pid) {
    Gallerix.fetch(Gallerix.settings.fetchURL + pid, false, false);
  }
  else if (Gallerix.settings.mode == 'grid') {
    Gallerix.fetch(Gallerix.settings.fetchURL + Gallerix.initial, false, false);
    window.location.hash = "#";
  }
  else {
    Gallerix.fetch(Gallerix.settings.fetchURL + Gallerix.initial, false, true);
  }
 
  // As soon as we complete the first fetch, we have finished bootstrapping.
  Gallerix.bootstrap = true; 
 
});




/**
 * Bootstrap. Loads in settings, activates flags and switches into the 
 * correct mode. Any elements already in the DOM related to Gallerix
 * are activated.
 *
 */
Gallerix.init = function() {
  var path = window.location.href;

  var regex = /picture=([0-9]*)/;
  var match = path.match(regex);
  
  Gallerix.pid = match ? match[1] : 0;
  
  var fragment = path.split('#')[1]; // We want to know what pid the user provided, if any.  
  Gallerix.pid = (fragment == undefined) ? Gallerix.pid : fragment; // If undefined, ignore the pid.

  // Load settings.
  Gallerix.settings = Drupal.settings['gallerix'];
  Gallerix.gridLoaded = false;
  Gallerix.mode = Gallerix.pid ? 'viewer' : Gallerix.settings.mode;
  Gallerix.initial = Gallerix.pid ? Gallerix.pid : Gallerix.settings.defaultImage;
  Gallerix.seed = '';
  Gallerix.bootstrap = false;
  
  // Initialize the flag system.
  Gallerix.resetFlags();
  
  // Initialize the cycle system.
  Gallerix.cycle = {};  
  
  $('.gallerix-grid-link').click(function () {
    Gallerix.switchModes();

    return false;
  });
  
  
  Gallerix.activateLinks();
}





/**
 * Creates or resets buffering flags for each component.
 *
 */
Gallerix.resetFlags = function() {
  Gallerix.preparationFlags = {};
  Gallerix.callbackFlags = {};

  for (var component in Gallerix.settings.preparations) {
    Gallerix.preparationFlags[component] = false;
  }  
  
  for (var component in Gallerix.settings.callbacks) {
    Gallerix.callbackFlags[component] = false;
  }
  
  
}


/**
 * Flag a component indicating it's ready.
 *
 */
Gallerix.flag = function(component) {
  
  switch (Gallerix.state) {
    case 'preparation': {
      var callback = 'transition';      
      var flagType = 'preparationFlags';
      break;
    }
    case 'callback': {
      var callback = 'finalize';
      var flagType = 'callbackFlags';
      break;
    }
   
  
  }

  Gallerix[flagType][component] = true;
   
  if (Gallerix.checkFlags(flagType)) {
    Gallerix[callback]();
  }

}





/**
 * Checks all flags. If all flags are true, carry on with transition.
 *
 */
Gallerix.checkFlags = function(flagType) {
  
  for (var component in Gallerix[flagType]) {
    if (!Gallerix[flagType][component]) {
      return false;
    }
  }
  
  

  return true;
}



/**
 * Go through each link, add fading and fetching behavior.
 * This function can be called multiple times, since it will only
 * apply behaviors to new elements in the DOM. 
 *
 */
Gallerix.activateLinks = function() {
  $('.gallerix-picture-link').each(function() {
      if (!$(this).is('.activated')) {
        $(this).click(function() {
          Gallerix.fetch(this.href);     
          return false;
        });
        
        var thumbnail = $(this).find('.gallerix-thumbnail.translucent');
        
        $(thumbnail).css('opacity', .6);
        
        var mouseover = function () {
          $(thumbnail).css('opacity', 1);
          return true;
        }
        var mouseout = function () {
          $(thumbnail).css('opacity', .6);
          return true;
        }       

        $(thumbnail).hover(mouseover, mouseout);

        $(this).addClass('activated');
        
      }
      
      
  });  
}





/**
 * Flag the grid for reloading.
 *
 */
Gallerix.reloadGrid = function() {
  Gallerix.gridLoaded = false;
  
}




/**
 * This function switches between the viewer mode, and the grid mode.
 *
 * It keeps track of what mode Gallerix is in, and whether or not the grid
 * has ever been loaded yet. Calling reloadGrid() will force this method to
 * load the grid again.
 *
 */
Gallerix.switchModes = function() {
  if (!Gallerix.bootstrap) {
    Gallerix.mode = Gallerix.settings.mode;
  }
  Gallerix.mode = (Gallerix.mode == 'viewer') ? 'grid' : 'viewer';
  
  if ( false ){ //!Gallerix.gridLoaded) {
    $.get(Gallerix.settings.gridURL, null, function (data) {
      $('#gallerix-grid').html(data);
      
      $('#gallerix-viewer').hide();
      $('#gallerix-grid').show();
      Gallerix.gridLoaded = true;
      
      
      
      if (Gallerix.mode == 'viewer') {
        $('#gallerix-grid-link').html('All Photos');
        window.location.hash = "#" + (pid ? pid : "");
          
      }
      else {
        $('#gallerix-grid-link').html('Single Photo');  
        window.location.hash = "";    
      }
        
      Gallerix.activateLinks();                    
    
    });
    
  }
  else {
    $('#gallerix-viewer').toggle();
    $('#gallerix-grid').toggle();
    
    if (Gallerix.mode == 'viewer') {
      $('#gallerix-grid-link').html('All Photos');    
      window.location.hash = "#" + (Gallerix.pid ? Gallerix.pid : "");
        
    }
    else {    
      $('#gallerix-grid-link').html('Single Picture');  
      window.location.hash = "#";    
    }
  }
  


}




/**
 * Preparation Callback.
 *
 * Fades out the main image to prepare it for replacement.
 *
 */
Gallerix.fn.hideImage = function() {

  // We do not wish to fade out since we are loading a cached picture.
  if (Gallerix.cache[Gallerix.cycle.pid] != undefined) {
    Gallerix.flag('gallerix_frame');
    return;
  }
  
  $('#gallerix-loader').css('background', 'url(' + Gallerix.settings.loaderImage + ') no-repeat center center');
  $('#gallerix-display').fadeTo(200, 0.001, function () {
  
    Gallerix.flag('gallerix_frame');   
  
  });
  

} 


/**
 * Callback.
 *
 * Fades in the main image after the AJAX request is done, and the buffer is loaded.
 *
 */
Gallerix.fn.showImage = function(image) {

  // We can assume the picture is already loaded if it's cached.
  if (Gallerix.cache[Gallerix.cycle.pid] != undefined) {
    _loadImage();
    return;
  }

  var imageBuffer = new Image(image['frameWidth'], image['frameHeight']);
  imageBuffer.onload = function() {
    _loadImage();
  };
  imageBuffer.src = image['framePath'] + Gallerix.seed;


  function _loadImage() {
    $('#gallerix-loader').css('background-image', 'none');     
    $('#gallerix-frame').attr({src: image.framePath + Gallerix.seed, width: image.frameWidth, height: image.frameHeight, title : image.caption});
    $('#gallerix-display').fadeTo(200, 1, function() { 
      Gallerix.flag('gallerix_frame');      
    });

  }

       
} 




/**
 * Callback.
 *
 * Updates all thumbnails once the AJAX request is done, and the buffer is loaded.
 *
 */
Gallerix.fn.updateThumbnails = function(image) {
  var thumbnails = image['thumbnails'];   
  
  // We can assume the thumbnails are loaded if they're cached.
  if (Gallerix.cache[Gallerix.cycle.pid] != undefined) {
    _updateThumbnails();
    return;
  }
  
  var buffer = new Array();
  var size = 0;
  
  for (var thumbnail in thumbnails) {
    size++;
  }
  
  
  
  //Boolean array holding flags.
  var flags = new Array(size);
  var count = 0;
  
  
  /** 
   * Creates a buffering system. Everytime an image is loaded, a flag is
   * set in an array. Once every flag is set, thumbnails are uploaded.
   *
   */
  for (var thumbnail in thumbnails) {
    buffer[count] = new Image(1, 1);
    buffer[count].flag = count;
    buffer[count].onload = function () {
      
      
      flags[this.flag] = true;
      
      if (_checkFlags()) {     
        _updateThumbnails();     
        return true;
      }
    
    }
    buffer[count].src = thumbnails[thumbnail].path + Gallerix.seed;
    
    count++;
  }
  
  /**
   * Helper function goes through each thumbnail and updates it.
   *
   */
  function _updateThumbnails() {
    for (var thumbnail in thumbnails) {
      $('#' + thumbnail).attr('href', thumbnails[thumbnail].link).find('img').attr('src', thumbnails[thumbnail].path + Gallerix.seed).attr('title', thumbnails[thumbnail].caption);
    }
    Gallerix.flag('gallerix_links');        
  };
  
  /** 
   * Makes sure all thumbnails have been cleared.
   *
   */
  function _checkFlags() {
    for (var x = 0; x < size; x++) {
      if (flags[x] == undefined) {
        return false;
      }
    }
    
    return true;
  };  



}




Gallerix.refresh = function(refresh) {

  if (refresh == undefined) {
    refresh = true;
  }
  
  Gallerix.fetch(Gallerix.settings.fetchURL + Gallerix.pid, refresh);   
  
}



/**
 *  The main function to fetch a picture. 
 *  
 *  All picture switching should be done through this function.
 *  Before fetching, this function will fire preparation callbacks.
 *
 * @param location is a URL including a validated PID.
 * @param refresh is a boolean which will force the browser not to cache.
 * @param grid indicates this function should not switch to single view.
 *        Instead, the picture will load in the background.
 */
Gallerix.fetch = function(location, refresh, track) {
  
  var url = Gallerix.url(location);
  var pid = Gallerix.getPid(url);
  
  // Prepare the random seed if requested.
  Gallerix.seed = refresh ? '?rand=' + Math.random() : '';
  
  // Reset all flags.
  Gallerix.resetFlags();
  
  Gallerix.state = 'preparation';
  
  // Update the global cycle variables.
  Gallerix.cycle = {};
  Gallerix.cycle.url = url;
  Gallerix.cycle.refresh = !(refresh == false || refresh == undefined);
  Gallerix.cycle.track = (track == true || track == undefined);
  Gallerix.cycle.pid = pid;
  
  // Execute preparations for all components.
  for (prepare in Gallerix.settings.preparations) {
    Gallerix.fn[Gallerix.settings.preparations[prepare]]();
  }
  
  //Gallerix.current = Gallerix.pid;
  
}



Gallerix.transition = function() {   
  
  
  
  var _transition = function(image) {
    Gallerix.state = 'callback';
    Gallerix.cycle.image = image;
    
    for (callback in Gallerix.settings.callbacks) {
      Gallerix.fn[Gallerix.settings.callbacks[callback]](image);
    }    
  }
  
  
  // We only need to make a request if it hasn't been made already, or if 
  // refresh is marked as true.
  if (Gallerix.cache[Gallerix.cycle.pid] != undefined && !Gallerix.cycle.refresh) {
    _transition(Gallerix.cache[Gallerix.cycle.pid]);
  }
  else {
    $.get(Gallerix.cycle.url, null, function(data) {
      var image = Gallerix.parseJson(data);
      
      if (!image['success']) {
        Gallerix.setError(image['message']);
      }
      else {
        _transition(image);
      }
    });
  }
}


Gallerix.finalize = function() {

  var image = Gallerix.cycle.image;
  
  //Reset the message box.
  Gallerix.clearMessage();
  
  if (Gallerix.cycle.track) {
    window.location.hash = '#' + image['key'];    
  }
  
  Gallerix.pid = image['key'];
  
  // Store the request in a static cache.
  Gallerix.cache[image['key']] = image;
    
}




/**************************** Utilities *******************************/

/**
 * Converts a regular HTML address to an AJAX one.
 *
 */
Gallerix.url = function(incoming) {

  var regex = /picture=([0-9]*)/;
  
  if (regex.test(incoming)) {
    var match = incoming.match(regex)
    var url = Gallerix.settings.fetchURL + match[1];
  }
  else {
    var url = incoming;
  }
 
  return url;
}

/**
 * Get the PID of a picture from a URL.
 *
 */
Gallerix.getPid = function(url) {
  var index = url.lastIndexOf('/');
  return url.substring(index + 1);
  
}


/**
 * Clears the local cache. If a pid is given, only that picture will be
 * deleted from the cache. Otherwise, the entire cache is deleted.
 *
 */
Gallerix.clearCache = function(pid) {
  if (pid != undefined) {
    delete Gallerix.cache[pid];
  }
  else {
    Gallerix.cache = {};
  }
}



