// If jQuery doesn't make it from the CDN
window.jQuery || document.write('<script src="/scripts/jquery.js">\x3C/script>');
/**
CSS Hooks
---------
Custom css hooks for CSS animation.
*/
// 
(function($) {
// A quick translate X only CSS hook, since we are only using it for the work slider right now.
$.cssHooks['translate'] = {
  set: function(elem, value) {
    // var prefix = 
    var div = document.createElement( "div" );
    $.support.transform =
    div.style.webkitTransform === ''? 'webkitTransform' :
    (div.style.MozTransform === ''? 'MozTransform' : 
    (div.style.OperaTransform === ''? 'OperaTransform' :
    (div.style.transform === ''? 'transform' : false)));
    elem.style[$.support.transform] = 'translate(' + value + ', 0)';
  }
}

})(jQuery);

var SF = SF || {};
// Cache
var $work = $('#work');
var isWebkit = $.browser.webkit;

SF = (function($) {
  /**
    Private Functions
    All our AJAX calls will reside here
  */
  
  /**
    getWorkCategory
    ---------------
    @description Get all the work items of a specified category.
    @private
    @param {String} category The work category you'd like to load
    @returns {Array} AJAX JSON response.
  */
  var getWorkCategory = function(category) {
    return $.getJSON('/feed/category/' + category);
  };
  
  /**
    getWorkItemDetail
    ---------------
    @description Gets a specific work item
    @private
    @param {String} item The work item you'd like to load
    @returns {Array} AJAX JSON response.
  */
  var getWorkItemDetail = function(item) {
    return $.getJSON('/feed/detail/' + item);
  };
  
  /**
    renderWorkThumbs
    ----------------
    @private
    @param img
    @return {Object} Returns successfully load image data.
  */
  var renderWorkThumbs = function(img) {
    var dfd = $.Deferred();
    var img = new Image();
    $(img).load(dfd.resolve(this.src)).attr('src', img);
    return dfd;
  };
    
  return {
    
    // The current section.
    _currentSection: null,
    
    // If in work, the current category.
    _currentCategory: null,
    
    // If a work item is loaded, this be it.
    _currentWorkItem: null,
    
    // Cache a category return array here.
    _workItemsCache: [],
    
    /**
      tabs
      ---- 
      @description Controls About Us section tabs, ignores work filters.
    */
    tabs: function() {
      $('.subnav').not('#work-filter').each(function() {
        var $subnav = $(this);
        var $tabTargets = $(this).parent().find('.tab');
        $(this).find('a').click(function(e) {
          e.preventDefault();
          var url = this.hash;
          $(this)
            .parents('ul')
              .find('a').removeClass('selected')
              .end()
            .end()
          .addClass('selected');
          
          $tabTargets
            .hide()
            .filter(url)
            .show()
            .trigger('makeColumns');
        }).filter(':first').trigger('click');
      });
    },
    
    /**
      closeSections
      -------------
      @description Closes the current section. Really!
    */
    closeSections: function() {
      var $current = $(document.getElementById(SF._currentSection));
      var $minimizeButton = $current.find('header > button.minimize');
      
      if (head.csstransitions) {
        $minimizeButton
          .removeClass('open-section-animation')
          .addClass('close-section-animation')
          .prop('disabled', 'disabled');
      } else {
        $minimizeButton.hide().prop('disabled', 'disabled');
      }
      
      $('.content:visible').slideUp(500, 'easeInOutQuad', function() {
        if ($current.prop('id') == 'our-work') $work.empty();
      });
      
      $current.removeClass('current');
      SF._currentSection = null;
      SF._currentCategory = null;
      SF._currentWorkItem = null;
      SF.workNavigationIndex = 1;
      SF.workNavigationLength = 0;
    },
    
    /**
      addCloseButtons
      ---------------
      @description Goes through each section and appends a minimize button.
    */
    addCloseButtons: function() {
      $('.main-section').each(function() {
        var $closeButton = $('<button>', {
          'class': 'button minimize',
          text: 'X',
          click: SF.toggleSection,
          disabled: 'disabled'
        });
        $(this).find('header').append($closeButton);
      });
    },
    
    /**
      toggleSection
      -------------
      @description Toggles the current section to OFF.
    */
    toggleSection: function() {
      if (SF._currentSection) {
        window.location.hash = '#!/';
        SF.closeSections();
      }
    },
    
    /**
      animateSections
      ---------------
      @description 
      @param {String} section Recieves the current section from sectionController.
    */
    animateSections: function(section) {
      var section = section,
          offsetHeight = 0,
          currentIndex = 0,
          $currentSection = '',
          $currentSectionContent,
          // New Section
          $section = $(document.getElementById(section)),
          $sectionContent = $section.find('.content'),
          $minimizeButton = $section.find('button.minimize');
          
      // If there is already a currently visible section
      if (SF._currentSection) {
        $currentSection = $(document.getElementById(SF._currentSection));
        $currentSectionContent = $currentSection.find('.content');
        currentIndex = $currentSection.index();
        
       // Figure out where we are, and adjust the offset height accordingly.
        if ($section.index() > currentIndex) {
          offsetHeight = ($currentSectionContent.length) ? 
                          $currentSection.height() - 70 : 0;
        }
      }
      
      // If we're near the top of the page, don't scroll down.
      var y = ($section.offset().top - offsetHeight);
      var scrollTo = (section == 'whats-new' || section == 'about-us') ? 0 : y;
      
      // Close the current section.
      if (SF._currentSection) SF.closeSections();
      
      // TODO: Move this into a function if possible
      $('html:not(:animated),body:not(:animated)').animate({
        scrollTop: scrollTo
        }, 500, 'easeInOutQuad');
      // Open the selected section
      $section.addClass('current').find('.content').slideDown(500, 'easeInOutQuad');
      
      if (head.csstransitions) {
        $minimizeButton
        .removeClass('close-section-animation')
        .addClass('open-section-animation')
        .prop('disabled', '');
      } else {
        $minimizeButton.show().removeAttr('disabled');
      }
      
      // Set the global var
      SF._currentSection = section;
    },
    
    /**
      sectionController
      -----------------
      @description This is mission control. A basic controller that will either 
      toggle a section of static content or render the work.
      @param {Object} args An object containing the Route fragments
    */
    sectionController: function(args) {
      var section = args.section;
      // First perform a quick check that the section exists
      if ($(document.getElementById(section)).length) {
        // If we're loading work, do a couple different things
        if (section == 'our-work') {
          var category = (typeof args.category !== 'undefined') ? args.category : 'featured';
          var workItem = (typeof args.work !== 'undefined') ? args.work : null;
          
          $.when(getWorkCategory(category)).then(function(data) {
            // Add the category to each item.
            $.map(data.items, function(num) {num['category'] = category;});
            
            // SF._workItemsCache = data.slice(0); // Cache the results
            $('#work-filter').find('a').removeClass('selected');
            $('a#work-category-' + category).addClass('selected');
            
            // Run the render methods
            if (category != SF._currentCategory) {
              SF.renderWork(data);
              SF._currentCategory = category;
            }
            if (section != SF._currentSection) SF.animateSections(section);
            if (workItem) {
            	if (SF._currentCategory == null) {
            		SF._currentCategory = category;
            	}
              SF.renderWorkDetail(workItem);
              SF._currentWorkItem = workItem;
              
            }
            
          }).fail(SF.epicFail);
        } else {
          // Otherwise just open the section.
          if (section != SF._currentSection) SF.animateSections(section);
        }
      // 404 handling
      } else {
        // alert('404!!');
      }
    },
    
    /**
      epicFail
      ----------
      @description What to do when something bad happens, or a 404
    */
    epicFail: function() {
      // alert('FML!');
    },
    
    /**
      renderWork
      ----------
      @description Renders the collection of work.
      @param {Object} data The JSON object from the getWorkCategory request.
    */
    renderWork: function(data) {

      var data = data.items;
      var dataObj = _.clone(data);
      var totalWorkItems = dataObj.length;
      var itemRange = _.range(0, totalWorkItems, 3); // Sets the ranges in clumps of 3
      // Move the work array into separate 3 item long arrays
      var items = {'Items': []}; // Store arrays here
      
      //Split the arrays in to clumps of 3
      _.map(itemRange, function(v, k) {
        var sliced = data.splice(0, 3);
        items['Items'].push(sliced);
      });
      
      $work.empty();
      
      // Render and append to the work pane
      $('#work-item-tmpl').tmpl(items.Items).appendTo($work);
      
      // Preload Images
      $.each(dataObj, function(k, v) {
        var halfToneImage = v.thumb_img_off;
        var fullColorImage = v.thumb_img_on;
        var $thumbnailHolder = $('#work-' + v.url_title).find('span.work-thumb');
        // Wait for the images to load, then append them to an hidden span, and fade in.
        $.when(renderWorkThumbs(halfToneImage), renderWorkThumbs(fullColorImage))
          .then(function(data) {
            $('<span>').css({'display': 'none'})
            	.append($('<img/>').attr({src: halfToneImage, 'class': 'work-half-tone'}))
            	.append($('<img/>').attr({src: fullColorImage, 'class': 'full-color-tone'}))
            .appendTo($thumbnailHolder)
            .delay(250)
            .fadeIn(500, 'easeInOutQuad', function() {
              $thumbnailHolder.removeClass('loading');
            });
          })
          // If it fails, hope that file is there anyways and load for IE.
          .fail(function() {
          	$('<span>').css({'display': 'none'})
            	.append($('<img/>').attr({src: halfToneImage, 'class': 'work-half-tone'}))
            	.append($('<img/>').attr({src: fullColorImage, 'class': 'full-color-tone'}))
            .appendTo($thumbnailHolder)
            .delay(250)
            .fadeIn(500, 'easeInOutQuad', function() {
              $thumbnailHolder.removeClass('loading');
            });
          });
      });
    },
    
    /**
      renderWorkDetail
      ----------------
      @description Renders the work detail view. Delegates are assigned to close, view thumnbails.
      @param {String} slug The URL fragment
      TODO: Add controls for view slides, different media types.
    */
    renderWorkDetail: function(slug) {
      SF.workNavigationIndex = 1;
      SF.workNavigationLength = 0;
      
      var $targetButton = $(document.getElementById('work-' + slug)).addClass('selected');
      var $buttonParentUl = $targetButton.parent().parent('ul');
      var buttonIndex = $targetButton.parent().index();
      // var workItemData = _.detect(SF._workItemsCache, function(num) {return num['slug'] == slug;});
      
      $.when(getWorkItemDetail(slug)).then(function(data) {
        var workImagesLength = data.detail.work_imgs.length;
        var workImagesHolderWidth = workImagesLength * 900;
        var workImageHeight = data.detail.work_imgs[0].dimensions[1];
      	//if (!workImageHeight) workImageHeight = 587;
        
        SF.workNavigationLength = workImagesLength;
        
        var $tmpl = $('#work-detail-tmpl').tmpl(data.detail, {
          // Parse the info string, since we can't pass html entities.
          parseInfo: function() {
            return this.data.info;
          }
        });
        
        // Clean out any old work items
        $work.find('.work-detail').remove().end()
          .find('a.work-item.selected').removeClass('selected');
        
        // Add a selected class to current work item
        $(document.getElementById('work-'+SF._currentWorkItem)).addClass('selected');
        
        // Append the template, hide, then slide down and slide too.
        $tmpl.hide().insertAfter($buttonParentUl)
          // Delegate any work related interaction here.
          .delegate('a.work-item', 'click', function(e) {
            // CHANGED: Keep around for now.
          })
          // Close the current work item.
          .delegate('button.close', 'click', function() {
	          SF.stopVideo();
            var closeToCategory = SF._currentCategory;
            window.location.hash = '#!/our-work/' + closeToCategory;
            $(document.getElementById('work-'+SF._currentWorkItem)).removeClass('selected');
            $('.work-detail').slideUp('slow', 'easeInOutQuad');
            $('html:not(:animated),body:not(:animated)').animate({
              scrollTop: $('#our-work').offset().top
            }, 800, 'easeInOutQuad');
            SF.workNavigationIndex = 1;
            SF.workNavigationLength = 0;
          })
          // Binds the <-|-> buttons and the ticker, see SF.workNavigation
          .delegate('span#work-item-index', 'updateIndex', SF.workNavigationIndexUpdater)
          .delegate('button.work-navigation', 'click', SF.workNavigation)
          // Bind the current image too!
          .delegate('#select-work-images img.work-image-fullsize', 'click', function() {
          	$('button#next-slide-btn').trigger('click');
          })
          // Bind the links to directly load a specific slide
          .delegate('#media-links a', 'click', SF.loadWorkSlide)
          // Open the launch button URl in a new window
          .delegate('button.launch-button', 'click', function() {
            window.open($(this).data('url'));
          })
          // Set the length the work images slider needs to be: (DISABLED)
          // .find('.work-images > ul').css('width', workImagesHolderWidth).end()
          // Add the down arrow...
          .addClass('nth-' + (buttonIndex + 1))
          // ... and slide 'er down.
          .slideDown(500, 'easeInOutQuad', function() {
            $('html:not(:animated),body:not(:animated)').animate({
              scrollTop: $('#work-work').offset().top
            }, 800, 'easeInOutQuad');
          });

          if (head.iOs) {
	          $('#select-work-images').swipe({
	          	threshold: {x: 150, y: 100},
	          	swipeLeft: function() {$('button#next-slide-btn').trigger('click');},
	          	swipeRight: function() {$('button#prev-slide-btn').trigger('click');}
	          });
          }
          
          //alert (data.detail.buckets);
          $('#select-work-images').addClass('img-clickable');
             
          // Load in each image on demand.
          $.each(data.detail.work_imgs, function(k, v) {
            var imageUrl = v.preview_img;
            var imageId = 'selection-' + k;
            var mediaType = v.media_type;
            var $videoTmpl = $('#work-banner-tmpl');
            var videoData = {
               imageId: imageId,
               layoutClass: v.work_type
            };
            /**
            If the mediaType is Flash, append the proper LI
            Has 2 flash container divs, only the second one is styled for 
            LB + BB layouts.
            */
            
            if( v.dimensions[1] > workImageHeight ){
            	workImageHeight = v.dimensions[1];
            }
            
            if (mediaType == 'flash') {
              // If Mobile Safari ...
              if (head.iOs) {
                videoData.mp4File = v.mp4_file;
                videoData.width = v.dimensions[0];
                videoData.height = v.dimensions[1];
                $('ul#select-work-images').append($videoTmpl.tmpl(videoData, {
                 	isMP4: true
                }));
              // ... otherwise play original Flash file
              } else {
                imageId.flashFile = v.flash_file;
                videoData.mp4File = v.mp4_file;
                $('ul#select-work-images').append($videoTmpl.tmpl(videoData, {
                  isFlash: true,
                  swf: v.flash_file,
                  w: v.dimensions[0],
                  h: v.dimensions[1]
                }));
                if (!k) {
              		swfobject.embedSWF(v.flash_file, imageId + '-flash', v.dimensions[0], v.dimensions[1], "10.0.0");
              	}
              }
              $work.find('.work-images').css('height', workImageHeight);
            // If the work type is a video demonstration, send the MP4/OGG files over
            } else if (mediaType == 'website' || mediaType == 'movie') {
              videoData.mp4File = v.mp4_file;
              videoData.oggFile = v.oggFile;
              videoData.width = v.dimensions[0];
              videoData.height = v.dimensions[1];
              videoData.preview_img = v.preview_img;
              $('ul#select-work-images').append($videoTmpl.tmpl(videoData, {
                isMovie: true
              }));
              $work.find('.work-images').css('height', videoData.height);
            // Load in regular work examples
            } else {
              $('ul#select-work-images').append($('<li id="' + imageId + '" class="loading"/>'));
              $.when(renderWorkThumbs(v)).then(function() {
                $('<img/>', {
                  src: imageUrl,
                  css: {'display':'none'},
                  'class': 'work-image-fullsize'
                }).appendTo('li#' + imageId).removeClass('loading').end()
                  .fadeIn(650, 'easeInOutQuad', function() {
                    $(this).parent().removeClass('loading');
                  });
              });
              $work.find('.work-images').css('height', workImageHeight);
            }
            
          });
			// If there are videos, run VideoJS.setup();
          $('ul#select-work-images').find('video').VideoJS();
      })
      .fail(SF.epicFail);
    },
    
    /* START WORK SELECT SCREENS NAVIGATION */
    
    // @default 1
    workNavigationIndex: 1,
    
    // @default 0
    workNavigationLength: 0,
    
    /**
      workNavigationIndexUpdater
      --------------------------
      @description Updates the currently viewed image index, eg {2}/5
    */
    workNavigationIndexUpdater: function() {
      $(this).text(SF.workNavigationIndex);
      if (SF.workNavigationIndex >= SF.workNavigationLength) {
        //$work.find('button.next').addClass('disabled');
        //$work.find('button.prev').removeClass('disabled');
        $('#select-work-images').removeClass('img-clickable');
      }
      else if (SF.workNavigationIndex <= 1) {
        //$work.find('button.prev').addClass('disabled');
        //$work.find('button.next').removeClass('disabled');
        $('#select-work-images').addClass('img-clickable');
      } else {
        //$work.find('button.prev').removeClass('disabled');
        //$work.find('button.next').removeClass('disabled');
        $('#select-work-images').addClass('img-clickable');
      }
    },
    /**
      workNavigation
      --------------
      @description Traverses the selection of work detail images.
      @param {Object} evt The button event object.
    */
    workNavigation: function(evt){
      var $button = $(this);
      var $nav = $button.parent();
      var $workItems = $('ul#select-work-images');
      var $currentLi = $('#selection-' + (SF.workNavigationIndex - 1));
      var speed = 500;
      
      // See if there's a video playing, and if so, pause it.
      SF.stopVideo();
      
      //$currentLi.
      $currentLi.find('object').not('.vjs-flash-fallback').hide();
      $work.find('.work-images').addClass('sliding');
      
      // <- Button
      if ($button.hasClass('prev')) {
      
        if (SF.workNavigationIndex > 1) {
          SF.workNavigationIndex--;
          var leftVal = (SF.workNavigationIndex * 900 * -1) + 900;
          if (head.iOs) {
            $workItems.css({
              'translate': leftVal,
            }, SF.endWorkNavigationAnimation);
          } else {
            $workItems.not(':animated').animate({
              left: '+=900px'
            }, speed, 'easeInOutQuad', SF.endWorkNavigationAnimation);
          }
          // If we're at the beginning, slide to the end.
        } else {
	        var leftVal = (SF.workNavigationLength * 900 * -1) + 900;
        	SF.workNavigationIndex = SF.workNavigationLength;
					if (head.iOs) {
            $workItems.css({
              'translate': leftVal,
            }, SF.endWorkNavigationAnimation);
          } else {
            $workItems.not(':animated').animate({
              left: leftVal
            }, speed, 'easeInOutQuad', SF.endWorkNavigationAnimation);
          }
        }
      }
      // -> Button
      if ($button.hasClass('next')) {
        if (SF.workNavigationIndex < SF.workNavigationLength) {
          var leftVal = SF.workNavigationIndex * 900 * -1;
          // Slide over
          if (head.iOs) {
            $workItems.css({
              'translate': leftVal
            }, SF.endWorkNavigationAnimation);
          } else {
            $workItems.not(':animated').animate({
              left: '-=900px'
            }, speed, 'easeInOutQuad', SF.endWorkNavigationAnimation);
          }
          SF.workNavigationIndex++;
        } else {
        	SF.workNavigationIndex = 1;
					var leftVal = 0;
        	if (head.iOs) {
            $workItems.css({
              'translate': leftVal,
            }, SF.endWorkNavigationAnimation);
          } else {
            $workItems.not(':animated').animate({
              left: leftVal
            }, speed, 'easeInOutQuad', SF.endWorkNavigationAnimation);
          }
        }
      }
      
      var id = SF.workNavigationIndex-1;
      var $newLi = $('#selection-' + id);
      
      if ($newLi.data('tmplItem')) {
      	if ($newLi.data('tmplItem').swf) {
      		swfobject.embedSWF($newLi.data('tmplItem').swf, 'selection-' + id + '-flash', $newLi.data('tmplItem').w, $newLi.data('tmplItem').h, "10.0.0");
      	} 
      }
      
      // Trigger the index view to update
      $('span#work-item-index').trigger('updateIndex');
      
      evt.preventDefault();
    },
    
    /**
    stopVideo
    ---------
    @description Simply stops the current video playing if it is present.
    */
    stopVideo: function() {
    	var $currentLi = $('li#selection-' + (SF.workNavigationIndex - 1));
    	// See if there's a video playing, and if so, pause it.
      if ($currentLi.find('video').length && head.video) {
        $currentLi.find('video')[0].player.pause();
      }
    },
    
    /**
      loadWorkSlide
      -------------
      @description Trigger a transition to a specific slide instead of relying
      on the arrow buttons to traverse.
      @param {Object} evt The button event object.
    */
    loadWorkSlide: function(e) {
      var $this = $(this);
      var target = parseFloat($this.attr('rel'));
      var $workItems = $('ul#select-work-images');
      var leftVal = (target * 900 * -1);
      if (head.iOs) {
        $workItems.css({
          'translate': leftVal
        }, SF.endWorkNavigationAnimation);
      } else {
        $workItems.not(':animated').animate({
          left: leftVal
        }, 800, 'easeInOutQuad', SF.endWorkNavigationAnimation);
      }
      
      SF.workNavigationIndex = target + 1;
      
      // If there's flash...
      var id = SF.workNavigationIndex-1;
      var $newLi = $('#selection-' + id);
      
      if ($newLi.data('tmplItem')) {
      	if ($newLi.data('tmplItem').swf) {
      		swfobject.embedSWF($newLi.data('tmplItem').swf, 'selection-' + id + '-flash', $newLi.data('tmplItem').w, $newLi.data('tmplItem').h, "10.0.0");
      	} 
      }
      
      // Clean up
      $('span#work-item-index').trigger('updateIndex');
      e.preventDefault();
      return false;
    },
    
    endWorkNavigationAnimation: function() {
      $work.find('.work-images').removeClass('sliding');
    }
  };
})(jQuery);

// INIT
$(function() {
  // Assign the tabs function
  SF.tabs();
  // Append section close buttons.
  SF.addCloseButtons();
  
  // Route.js Dispatcher, do not remove.
  var Dispatcher = {}; 
  Dispatcher._hashchange_last = ''; 
  Dispatcher._onhashchange=function(){
    if (Dispatcher._hashchange_last != location.hash) { 
      Dispatcher._hashchange_last = location.hash;
      route(location.hash).run();
    }
  };
  setInterval(function() {Dispatcher._onhashchange();}, 50);
  
  // Routes 
  route('#!/index').bind(SF.closeSections);
  route('#!/:section').bind(SF.sectionController);
  route('#!/:section/:category').bind(SF.sectionController);
  route('#!/:section/:category/detail/:work').bind(SF.sectionController);
  if (!window.location.hash) route('#!/whats-new').run();
  
  // Bind the page title to toggle the section.
  $('header#masthead').find('h1 a').click(function(e) {
    if (SF._currentSection == 'about-us') e.preventDefault();
    $(this).bind('click', SF.toggleSection);
  });
  
  // A little IE-friendlying, fills in for some CSS3 selectors.
  if ($.browser.msie) {
    $('#whats-new').find('ul.thumb-list li').filter(':nth-child(6n)').addClass('omega');
    $('#our-work').find('ul.thumb-list li').filter(':nth-child(3n)').addClass('omega');
    $('#our-team').find('ul.team li').filter(':nth-child(3n)').addClass('omega');
  }
  
  // Preload team frame
  var frame = new Image();
  frame.src = '/images/team_frame.png';
  
});
