var GalleryManager = function() {

  var _queued_photo = null
  var _currently_transitioning = false
  var _fading_in_photo_links = false
  var _slideshow_playing = false
  var _slideshow_timeout
  var _slideshow_interval = 4000


  /***************
  PUBLIC FUNCTIONS
  ***************/
  var switch_to_this_gallery = function(gallery_preview_el) {
    var g_el_to_show = $(gallery_preview_el)
    var all_g_els = $$('.galleryPreview').reverse()
    var num_galleries = all_g_els.size()

    var fade_time_per_thumbnail = 1.5 / num_galleries
    var delay_multiplier = fade_time_per_thumbnail / 4
    var delay_before_href_change = (delay_multiplier * (num_galleries - 1)) + fade_time_per_thumbnail

    all_g_els.each(function(g_el, index) {
      if(g_el == g_el_to_show) {
        var thumbnail_el = g_el.select('.thumbnail').first()
        new Effect.Opacity(thumbnail_el, {from: 1, to: .3, duration: fade_time_per_thumbnail, delay: index * delay_multiplier})
      }
      else {
        new Effect.Opacity(g_el, {from: 1, to: 0, duration: fade_time_per_thumbnail, delay: index * delay_multiplier})
      }
    })

    setTimeout(function() {
      window.location.href = g_el_to_show.href
    }, delay_before_href_change * 1000)
  }


  var return_to_list = function() {

  }


  var toggle_slideshow = function() {

  }


  var show_this_photo = function(photo_link_el) {
    if(!photo_link_el || !$(photo_link_el).visible()) {
      stop_slideshow()
      return false
    }

    // If there is already a photo in the queue then pretend that it was the one clicked
    if(_queued_photo) photo_link_el = $(_queued_photo)
    else photo_link_el = $(photo_link_el)

    var container_el = $('GalleryPhotoContainer')
    var caption_container_el = $('GalleryCaptionContainer')
    var old_photo_el = $$('.galleryPhoto').last()
    var old_photo_img_el = old_photo_el.getElementsByTagName('img')[0]
    
    if(old_photo_img_el && old_photo_img_el.src.include(photo_link_el.href)) return false

    if(!photo_link_el || photo_link_el.hasClassName('active')) return false
    $$('a.photoLink.active').invoke('removeClassName', 'active')
    photo_link_el.addClassName('active')

    set_photo_url_from_href(photo_link_el.href)
    
    if(_currently_transitioning) {
      _queued_photo = photo_link_el
      return false
    }    
    _currently_transitioning = true

    
    // Before beginning the transition, finish dimming the old photo AND caching the new one
    var old_photo_dimmed = false
    var new_photo_cached = false

    new Effect.Opacity(old_photo_el, {from: 1, to: .7, duration: .5, queue: 'end', afterFinish: function() {
      old_photo_dimmed = true
      if(new_photo_cached) transition_to_new_photo()
    }})

    var new_photo_el = $(document.createElement('div'))
    new_photo_el.setStyle('position: absolute').addClassName('galleryPhoto').hide()
    
    var new_photo_img = $(document.createElement('img'))
    new_photo_img.onload = function() {
      new_photo_cached = true
      if(old_photo_dimmed) transition_to_new_photo()
    }
    new_photo_img.src = photo_link_el.href

    new_photo_el.appendChild(new_photo_img)
    new_photo_el.appendChild($(document.createElement('div')).addClassName('topRightShadow'))
    new_photo_el.appendChild($(document.createElement('div')).addClassName('bottomRightShadow'))
    new_photo_el.appendChild($(document.createElement('div')).addClassName('bottomLeftShadow'))

    old_photo_el.insert({before: new_photo_el})

    var transition_to_new_photo = function() {
      
      old_photo_el.addClassName('transitioning')
      new_photo_el.addClassName('transitioning')
      
      var update_caption = function() {
        caption_container_el.innerHTML = photo_link_el.next().innerHTML
      }
      
      if(Prototype.Browser.IE)
        update_caption()
      else
        new Effect.Fade(caption_container_el, {queue: 'end', duration: .35, afterFinish: update_caption})
      
      // Because these are absolutely positioned we need to calculate
      // the left offset needed to make the image centered horizontally
      new_photo_el.setStyle('left: ' + Math.ceil(($('GalleryPhotoContainer').getWidth() - new_photo_el.getWidth()) / 2) + 'px')

      new Effect.Parallel([ new Effect.Appear(new_photo_el, {sync: true}),
                            new Effect.Move(old_photo_el, {x: 0, y: 75, sync: true}), 
                            new Effect.Opacity(old_photo_el, {sync: true, from: .7, to: .0}) ],
                            {queue: 'end', duration: .5, afterFinish: function() {

                              if(!Prototype.Browser.IE) 
                                new Effect.Appear(caption_container_el, {duration: .35})
                              
                              _currently_transitioning = false
                              new_photo_el.removeClassName('transitioning')

                              // Now that the effects are complete, remove all images 
                              // from the DOM except the one we've transitioned too
                              container_el.select('.galleryPhoto').without(new_photo_el).invoke('remove')
                              
                              if(!next_photo_link()) stop_slideshow()

                              if(_slideshow_playing) {
                                _queued_photo = null
                                clearTimeout(_slideshow_timeout)
                                _slideshow_timeout = setTimeout(function() {
                                  show_this_photo(next_photo_link())
                                }, _slideshow_interval)
                                return false
                              }

                              // If there is anything in the queue then shift the first
                              // item off of the array and begin transitioning to it
                              if(_queued_photo) {
                                var queued_photo = _queued_photo
                                _queued_photo = null
                                show_this_photo(queued_photo)
                              }
                            }})

      // Adjust the height of the photo container to match the new photo
      // but only if it actually changes
      if(container_el.getHeight() != new_photo_el.getHeight())
        container_el.morph('height: ' + new_photo_el.getHeight() + 'px', {queue: 'end', duration: .2})
    }

  }


  var toggle_slideshow = function() {
    _slideshow_playing ? stop_slideshow() : start_slideshow()
  }


  /***************
  PRIVATE FUNCTIONS
  ***************/
  var fade_in_the_gallery = function() {
    if(!$('GalleryContainer')) return false
    
    var title_el = $$('.galleryTitle').first()
    var description_el = $$('.galleryDescription').first()
    var container_el = $('GalleryPhotoContainer')
    var main_photo_el = $$('.galleryPhoto').last()
    var main_photo_img = main_photo_el.select('img').last()    
    
    if(!title_el.empty()) new Effect.Opacity(title_el, {duration: .3, queue: 'end'})
    if(!description_el.empty()) new Effect.Opacity(description_el, {duration: .3, queue: 'end'})

    if(!main_photo_img) return false
    
    var tmp_image = new Image()
    tmp_image.onload = function() {
      container_el.setStyle('height: ' + main_photo_el.getHeight() + 'px')
      new Effect.Opacity(main_photo_el, {duration: .3, queue: 'end', afterFinish: function() {
        fade_in_photo_links()
        main_photo_el.removeClassName('transitioning')
      }})
    }
    tmp_image.src = main_photo_img.src
  }


  var fade_in_photo_links = function() {
    if(_fading_in_photo_links) return false
    _fading_in_photo_links = true


    var finished_fading_these_photo_links = function() {
      _fading_in_photo_links = false
      if($$('#PhotoLinks a.photoLink.hidden').length > 0) fade_in_photo_links()
    }

    var photo_links = $$('#PhotoLinks a.photoLink.hidden')

    photo_links.each(function(photo_link_el, index) {
      if(!photo_link_el || !photo_link_el.hasClassName('hidden')) finished_fading_these_photo_links()
      var tmp_image = new Image()
      tmp_image.onload = function() {
        var final_opacity = (photo_link_el == photo_links.first() ? .4 : 1)
        new Effect.Opacity(photo_link_el, {to: final_opacity, duration: .3, delay: .1 * index, afterFinish: function() {
          photo_link_el.setOpacity('').removeClassName('hidden')
          if(photo_link_el == photo_links.last()) finished_fading_these_photo_links()
        }})
      }      
      tmp_image.src = photo_link_el.select('img').first().src
    })
    
  }


  var set_photo_url_from_href = function(href) {
    window.location.hash = $A($A(href.split('/')).last().split('_')).first()
  }


  var load_photo_from_url = function() {
    var photo_links = $$('#PhotoLinks a.photoLink')
    photo_links.each(function(photo_link_el) {
      var this_photo_id = $A($A(photo_link_el.href.split('/')).last().split('_')).first()
      var url_photo_id = window.location.hash.replace('#', '')
      if(this_photo_id == url_photo_id) {
        show_this_photo(photo_link_el)
        throw $break
      }
    })
  }


  var next_photo_link = function() {
    var current_photo_link = $$('a.photoLink.active').first()
    if(!current_photo_link) return false
    return current_photo_link.next().next()
  }


  var start_slideshow = function() {
    _slideshow_playing = true
    $('SlideshowToggle').update('Stop slideshow')
    
    // If there is no next_photo_link then we should start with the first one
    if(next_photo_link()) {
      setTimeout(function() {
        show_this_photo(next_photo_link())
      }, 1500)
    }
    else {
      show_this_photo($$('a.photoLink').first())
    }
  }


  var stop_slideshow = function() {
    _slideshow_playing = false
    $('SlideshowToggle').update('Start slideshow')
    clearTimeout(_slideshow_timeout)
  }


  var check_for_hidden_ui_to_reveal = function() {
    var num_of_photo_links = $$('.photoLink').length

    if($$('.galleryPhoto').first().getOpacity() == 0 && num_of_photo_links >= 1) {
      show_this_photo($$('a.photoLink').first())
    }

    if(!$('SlideshowToggle').visible() && num_of_photo_links >= 2) {
      new Effect.Appear('SlideshowToggle', {queue: 'end'})
    }
  }


  Event.observe(document, 'dom:loaded', fade_in_the_gallery)
  Event.observe(window, 'load', load_photo_from_url)
  Event.observe(window, 'unload', Prototype.emptyFunction) // for Safari


  return {
    switch_to_this_gallery: switch_to_this_gallery,
    return_to_list: return_to_list,
    toggle_slideshow: toggle_slideshow,
    show_this_photo: show_this_photo,
    toggle_slideshow: toggle_slideshow,
    fade_in_photo_links: fade_in_photo_links,
    check_for_hidden_ui_to_reveal: check_for_hidden_ui_to_reveal
  }

}()