// TODO: refactor to eliminate global variables.

$(document).ready(function() {
  var asset_switcher = new AssetSwitcher();
  var periodic_asset_switcher = new PeriodicAssetSwitcher(asset_switcher);
  new InputHandler(asset_switcher, periodic_asset_switcher);
});




function InputHandler(asset_switcher, periodic_asset_switcher) {
  this._asset_switcher = asset_switcher;
  this._periodic_asset_switcher = periodic_asset_switcher;
  this._configure_asset_switching_links();
  this._make_assets_switch_on_image_click();
}

InputHandler.prototype._configure_asset_switching_links = function() {
  var self = this;
  $('a.portfolio-asset-switcher').click(function() {
    self._periodic_asset_switcher.stop();
    var asset_index = $(this).attr('href').match(/\d+$/)[0];
    self._asset_switcher.switch_to(parseInt(asset_index, 10) - 1);
    // Stop normal processing, which would scroll page to element.
    return false;
  });
}

InputHandler.prototype._make_assets_switch_on_image_click = function() {
  var self = this;
  $('div.portfolio-asset-image').css('cursor', 'pointer').click(function() {
    self._periodic_asset_switcher.stop();
    self._asset_switcher.switch_to('next');
  });
}




function AssetSwitcher() {
  // If switch is already in progress, do not permit the beginning of another -- otherwise, odd layout
  // issues may occur as multiple assets are (partially) visible at once.
  this._asset_switch_in_progress = false;
}

// Accepts index='next', as well as index=<int>.
AssetSwitcher.prototype.switch_to = function(index) {
  if(this._asset_switch_in_progress) return;
  // Must use selector 'div.portfolio-asset' for IE 6 compatibility. jQuery seems somewhat broken -- if
  // one runs $('.portfolio-asset'), "undefined" is returned. This should never happen -- even if the
  // selector matches no elements, jQuery should return an empty set. Regardless, it's an easy workaround.
  var assets = $('div.portfolio-asset');
  var currently_visible = assets.filter(':visible');

  if(index == 'next')        index = assets.index(currently_visible) + 1;
  if(index >= assets.length) index = 0;
  var target = assets.eq(index);

  // If one does not pull actual element out of jQuery set by using "[0]", equivalence test fails even
  // if sets are identical.
  if(target[0] == currently_visible[0]) return;
  this._asset_switch_in_progress = true;
  var self = this;
  this._switch_assets(currently_visible, target, function() {
    self._asset_switch_in_progress = false;
  });
  $('a.portfolio-asset-switcher').removeClass('active').eq(index).addClass('active');
}

AssetSwitcher.prototype._switch_assets = function(old_asset, new_asset, after_fade_complete) {
  var period = 1000;
  // Immediately after fading of old_asset begins, set absolute position on new_asset so that, as it
  // fades in, it is overlain directly on old_asset. (If this is not done, new_asset will be part of
  // layout flow, meaning it will appear *below* old_asset until old_asset disappears completely.)
  // Once old_asset has fully disappeared, remove position property on new_asset so that it rejoins
  // layout. (If this is not done, since old_asset is gone, the descriptive text below the asset
  // will flow up, so that it is obscured behind the image -- remember, if element's position is set
  // to absolute, it is removed from the layout flow.)
  old_asset.fadeOut(period, function() {
    new_asset.css('position', '');
    if(after_fade_complete) after_fade_complete();
  });
  new_asset.css('position', 'absolute').css('top', old_asset.position().top);
  new_asset.fadeIn(period);
}




function PeriodicAssetSwitcher(asset_switcher) {
  this._asset_switcher = asset_switcher;
  this.start();
}

PeriodicAssetSwitcher.prototype.start = function() {
  var self = this;
  this._timer_id = window.setInterval(function() {
    self._asset_switcher.switch_to('next');
  }, 4000);
}

PeriodicAssetSwitcher.prototype.stop = function() {
  window.clearInterval(this._timer_id);
}

