
//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).addClass('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);
    }
  });
}

/**
 * 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-original-link').attr({href: image.originalPath});
    $('#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 href 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(href, refresh, track) {
  var url = Gallerix.url(href);
  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)
    return Gallerix.settings.fetchURL + match[1];
  }
  return incoming;
}

/**
 * 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 = {};
  }
}
// vim: ts=2 sw=2 et syntax=javascript

