// requires: global `smoothieCinema`, an array of slide data
;$(function () {
  var slideData, ojAnimator, smoothieAnimator, likeButton, container, ie

  // We don't use fades for oldie with pngs
  ie = $('html').hasClass('oldie')

  // The server should write this variable into the page
  // We change the format a little
  slideData = formatSlideData(window.smoothieCinema)

  // Animation settings
  animations = {
    defaults: {
      // Fade in for each object
      fadeIn: { delay: 120, duration: 700 },

      // Fadout entire slide
      fadeOut: 500,

      // Movement jquery animation settings
      movement: { queue: false, duration: 400, easing: 'linear' }
    },

    // Movement for smoothie and OJ
    smoothie: {
      move1: {left: '+=12px', top: '+=9px'},
      move2: {left: '+=9px', top: '-=2px'}
    },

    oj: {
      move1: {left: '-=12px', top: '+=9px'},
      move2: {left: '-=9px', top: '-=2px'}
    }
  }
  
  // Grab elements
  container = $('div.smoothie-cinema')

  // Listen for clicks
  container.delegate('.arrow', 'click', clickArrow)

  // Create animators
  ojAnimator = new SlideAnimator(
    container.find('.oj'), 
    $.extend({}, animations.defaults, animations.oj), 
    slideData.oj,
    'Originals'
  )
  
  smoothieAnimator = new SlideAnimator(
    container.find('.smoothie'),
    $.extend({}, animations.defaults, animations.smoothie), 
    slideData.smoothie,
    'Smoothie'
  )


  // Handle an arrow click - transition to next slide ONLY for 1 screen
  function clickArrow (e) {
    var animator
    e && e.preventDefault()
    
    // Get the oj or smoothie animator and transition slide
    animator = $(e.currentTarget).is('.left') ? smoothieAnimator :  ojAnimator
    animator.queueNextSlide()
  }


  // Object that animates between slides
  function SlideAnimator (el, settings, data, trackingCategory) {
    var actors, index, likeButton, slidesQueue

    // We queue slides to transition to on this element.
    // That way the user can click multiple times and it won't
    // interupt the animations
    slidesQueue = $({})

    // Grab dom elements
    actors = {
      text: el.find('.text'),
      drink: el.find('.drink'),
      move1: el.find('.move1'),
      move2: el.find('.move2'),
      fade1: el.find('.fade1')
    }
    actors.all = el.find('.actor')
    likeButton = el.find('.fb-like')

    // Determine initial slide to show.  Default is 0, overriden by `selected: true`
    // attribute on a slide.
    index = 0
    $.each(data, function (i, item) {
      if (item.selected)  index = i
    })
    index--
    
    // Start the show
    transitionToNextSlide()

    // Export
    this.queueNextSlide = queueNextSlide
    return;

    function queueNextSlide () {
      slidesQueue.queue(transitionToNextSlide)
    }

    // Fade out the current slide, fade in the new one.  On IE, we just show/hide.
    // Show/hide the facebook like button seperately, to avoid an iframe flash.
    function transitionToNextSlide (callback) {
      var url, trackingName
      index = (index + 1) % data.length
      
      preloadNextSlide(function () {
        url = data[index].url

        if (ie)  {
          el.hide()
          loadLikeButton(likeButton, url)
          animateInSlide(screen, settings, data[index])
        }
        else {
          el.fadeOut(settings.fadeOut, function () { 
            likeButton.hide()
            loadLikeButton(likeButton, url, function () {
              likeButton.show()
            })
            animateInSlide(screen, settings, data[index])
          })
        }
        preloadNextSlide()

        // Extract tracking name from url.  Assumes name is everything after "?m=" in the url
        trackingName = unescape(url.split('?m=')[1])
        trackSlide(trackingName)
      })
    }

    function trackSlide(name) {
      try {
        console.log('tracking slide', trackingCategory, name)
        _gaq.push(['_trackEvent', trackingCategory, 'View', name])
      } catch (err) { console.log('Error tracking!') }
    }

    function preloadNextSlide (callback) {
      var images, nextIndex, nextSlide
      nextIndex = (index + 1) % data.length
      nextSlide = data[nextIndex]

      // Pre-load images.  note: $.map removes nulls/undefineds,
      // and we convert "" to null.
      images = 'text drink move1 move2 fade1'.split(' ')
      images = $.map(images, function (name) { return nextSlide[name] || null })
      loadImages(images, callback)
    }


    // Fade in order: text, drink, move1, move2, fade1.
    // move1 and move2 move slightly as they fade in.
    function animateInSlide(slide, settings, data) {
      var animationCompleteIn, delay = 0

      // Hide actors inside the slide, and show the slide
      if (ie)  actors.all.hide()
      else  actors.all.css('opacity', 0)
      el.show()

      fadein('text')
      fadein('drink')
      fadein('move1')
      fadein('move2')
      fadein('fade1')

      // Indicate that we're done with this animation after the last element has 
      // finished animating
      animationCompleteIn = delay + settings.fadeIn.duration + 100
      setTimeout(function () { slidesQueue.dequeue() }, animationCompleteIn)
      return;

      // Fades in the given object, if we have a url for it in the slide data.
      // Possibly moves it too
      function fadein (name) {
        var obj, url, movement
        obj = actors[name]
        url = data[name]

        if (!url)  return

        // Calculate new delay
        if (!ie)  delay += settings.fadeIn.delay
        movement = settings[name]

        // Update background image and maybe move element
        obj.backgroundImage(url)
        if (movement) obj.css(invert(movement))    

        setTimeout(function () {
          // Maybe Move back to its original position
          if (movement)  obj.animate({top:0, left: 0}, settings.movement)
          // FadeIn, unless IE
          if (ie)  obj.show()
          else  obj.animate({opacity: 1}, settings.fadeIn.duration)
        }, delay)
      }
    }       
  }

  function loadLikeButton(el, url, callback) {
    el.find('iframe').remove()
    return create(url).appendTo(el).load(callback)
    // ~
    function create (url) {
      return $('<iframe src="http://www.facebook.com/plugins/like.php?href=' +
              encodeURIComponent(url) +
              '&amp;send=false&amp;layout=button_count&amp;width=50&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;font&amp;height=21" ' +
              'scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:21px;" allowTransparency="true"></iframe>')
    }
  }

  // We restructure the data from a flat array of slides to hash like:
  //    { oj: [...], smoothie: [...] }
  function formatSlideData(list) {
    if (!list || !list.length)  throw "window.smoothieCinema data not present"
    var result = {oj: [], smoothie: []}
    $.each(list, function (i, item) {
      result[item.type].push(item)
    })
    return result
  }
 

  // For each value in a given position object, swaps the '-' and '+' for the first character
  // E.g. invert({left: '-=4px'}) // => {left: '+=4px'}
  function invert (position) {
    var k, value, negative, result = {}
    for (k in position) {
      value = position[k]
      result[k] = (value[0] == '-') ? value.replace('-', '+') :  value.replace('+', '-') 
    }
    return result
  }

  ///////////////////////
  //  Image Pre- Loading
  ///////////////////////
  // Use a timeout so failing to preload image doesn't stop the page from loading
  // Can pass 'false' for timeout to never timeout
  function loadImages (images, callback, timeout) {
    var loaded = 0, i = 0, total = images.length, called = false
    if (timeout !== false)  setTimeout(callCallback, timeout || 4000)
    for (; i < total; i++) $.extend(new Image, { onload: onload, src: images[i] })
    function onload () {
        if (++loaded === total)  callCallback()
    }
    function callCallback() {
        if (!called && callback)  callback()
        //window.console && window.console.log('loaded', loaded, 'of', total)
        called = true
    }
  }                         


});


