
var TS = window.TS || {}; // The Supply's global scope object

TS.IS_TABLET = false;

(function($){

  TS.initialize = function() {
    
    var $win = $(window),
        $body = $('body'),
        $wrapper = $('#wrapper'),
        $bgBox = $('#bg-box'),
        $sections = $('section'),
        $navLinks = $('nav a'),
        $nextSectionTab = $('#next-section-tab'),
        $mouseFollower = null,
        _sectionTabPulse = null,
        _curSectionId = null,
        _curSectionIndex = 0,
        _queuedSectionId = null,
        _sectionTransOffsetY = 100,
        _transInTimeout = null,
        _isTransitioningSections = false,
        _backForthDir = 0,
        _backForthOffsetY = 15,
        _backForthOffsetX = -35,
        _backForthMargin = 70,
        _forthThresholdY = 0,
        _backThresholdY = _backForthMargin,
        _isBackForthNavActive = false;
        _backForthNavTimeout = null,
        _deltaOffset = 0,
        _curDeltaDir = 0,
        _deltaThreshold = 0.3,
        _sectionIndexes = {},
        _isMouseFollowActive = false,
        _mFollowPos = {x: 0, y: 0},
        _mousePos = {x: 0, y: 0},
        _centerPos = {x: 0, y: 0},
        _transDir = 1,
        _directionOverride = null,
        _bgBoxMouseMove = null,
        _homeAutoAdvance = null,
        _w = 0,
        _h = 0;
    
    function _init() {
      debug.log("TS.site :: initialize");
      
      TS.IS_TABLET = $('html').hasClass('ipad');
      
      // setup sections for transitions
      $sections.each(function(i) {
        var $section = $(this);
        
        _sectionIndexes[$section.attr('id')] = i;
        
        $section.css({
          'top': _sectionTransOffsetY+'px',
          'opacity': '0'
        })
        .addClass('hidden');
      });
      
      // setup back/forth mouse follower
      _mFollowPos.x = $wrapper.outerWidth() * 0.5;
      _mFollowPos.y = $wrapper.outerHeight() * 0.5;
      $mouseFollower = $('<div id="mouse-follower"></div>');
      $mouseFollower.css({
        'opacity':'0',
        left:_mFollowPos.x,
        top:_mFollowPos.y
      });
      $wrapper.append($mouseFollower);
      
      $mouseFollower.bind('click', _onMouseFollowerClick);
      
      // setup section navigation links
      $navLinks.bind('click', _onSectionLinkClick);
      $('.section-link').bind('click', _onSectionLinkClick);
      $nextSectionTab.bind('click', _onSectionLinkClick).css('opacity', '0');
      _sectionTabPulse = $nextSectionTab.pulse(0.3).data('Pulse');
      
      // watch mouse events
      $wrapper.bind('mousewheel', _onMouseWheel);
      $wrapper.bind('mousemove', _onMouseMove);
      
      // only setup background movement for desktop, too much cpu on tablet
      if (!TS.IS_TABLET) {
        _bgBoxMouseMove = $bgBox.mouseRangeMovementItem({
      			movementSizeX: 47,
      			movementSizeY: 77
      	}).data('MouseRangeMovementItem');
      }
      
      $win.bind('resize', _onResize);
      _onResize();
            
      // ...and we're off
      _setSection('home');
      setTimeout(function() {
          $nextSectionTab.addClass(_curSectionId);
          $nextSectionTab.animate({opacity:1}, 450, function() { _sectionTabPulse.start(); });
          
          _homeAutoAdvance = setTimeout(function() {
              _setSection('about');
            },
            2600
          );
          
          
        },
        400
      );
      
      if (TS.IS_TABLET) {
        $wrapper.touchSwipe({
          orientation: 'vertical',
          swipeUp:_setSectionNext,
          swipeDown:_setSectionPrev
        });
       
       //window.addEventListener('onorientationchange', _updateOrientation, false);
      }
      
      _animate();
      
    }
    
    // ----------------------------------------------------------------
    
    function _onSectionLinkClick(e) {
      var $link = $(this);
      
      e.preventDefault();
      
      _setSection($link.attr('href').split('/')[1]);
    }
    
    // ----------------------------------------------------------------
    
    function _onMouseFollowerClick() {
      
      if ($mouseFollower.hasClass('back')) {
        _setSectionPrev();
      } else if ($mouseFollower.hasClass('forth')) {
        _setSectionNext();
      }
      
    }
    
    // ----------------------------------------------------------------
        
    function _onMouseWheel( event, delta, deltaX, deltaY) {
      
      var deltaDir = (delta > 0 ) ? 1 : -1;
            
      if (_isTransitioningSections) {
        return;
      }
      
      // keep track of scroll direction changes to reset offset
      if (deltaDir != _curDeltaDir) {
        _deltaOffset = 0;
        _curDeltaDir = deltaDir;
      }
      
      _deltaOffset += delta;
   
      if (Math.abs(_deltaOffset) > _deltaThreshold) {
        
        _deltaOffset = 0;
      
        if (_curDeltaDir > 0) {
          _setSectionPrev();
        } else if (_curDeltaDir < 0) {
          _setSectionNext();
        }
        
      }
      
    }
    
    // ----------------------------------------------------------------
    
    function _onMouseMove(e) {
          
      _mousePos.x = e.pageX;
      _mousePos.y = e.pageY;
          
      if (!_isMouseFollowActive) {
        _isMouseFollowActive = true;
      }
          
      _updateBackForth();
      
      _checkBackForthNav();
      
      // track top/bottom proximity for section navigation 
    }
    
    function _checkBackForthNav() {
      if (!_isBackForthNavActive || !_isMouseFollowActive) {
        return;
      }
        
      if (_backForthDir > 0 && _mousePos.y > _forthThresholdY) {
        _setSectionNext();
      }
    
      if (_backForthDir < 0 && _mousePos.y < _backThresholdY) {
        _setSectionPrev();
      }
      
    }
    
    // ----------------------------------------------------------------
    
    function _setSectionPrev() {
      var prevSectionIndex = _sectionIndexes[_curSectionId] - 1;

      if (prevSectionIndex < 0) {
        return;
      }
      
      _setSection($sections.eq(prevSectionIndex).attr('id'));
    }
    
    function _setSectionNext() {
      var nextSectionIndex = _sectionIndexes[_curSectionId] + 1;
      
      if (nextSectionIndex >= $sections.length) {
        return;
      }
      
      _setSection($sections.eq(nextSectionIndex).attr('id'));
    }
    
    // ----------------------------------------------------------------
    
    function _setSection(sectionId) {
      
      if (_homeAutoAdvance != null) {
        clearTimeout(_homeAutoAdvance);
        _homeAutoAdvance = null;
      }
      
      var outSectionId = _curSectionId
          outSectionIndex = _sectionIndexes[outSectionId],
          $inSection = null,
          boxDestX = 0;
      
      if (sectionId == _curSectionId) {
        return;
      }
      
      // update nav
      $navLinks.filter('.selected').removeClass('selected');
      $('#nav-'+sectionId).addClass('selected');
      
      // queue navigation attempt while transitioning
      if (_isTransitioningSections) {
        _queuedSectionId = sectionId;
        return;
      }
      
      _isTransitioningSections = true;
      _isBackForthNavActive = false;
      _curSectionId = sectionId;
      _curSectionIndex = _sectionIndexes[_curSectionId];
      $inSection = $('#'+_curSectionId);
      
      _updateBackForth();
            
      if (outSectionId !== null) {
        
        $outSection = $('#'+outSectionId);
        $outSection.addClass('out');        
        
        // fade out next section tab
        _sectionTabPulse.stop();
        $nextSectionTab.animate({opacity:0}, 250, function() {
          $nextSectionTab.removeClass(outSectionId);
        });
        
        // check which direction we're transitioning 
        if (outSectionIndex > _curSectionIndex) {
          _transDir = -1;
          $inSection.css({
            'top': -_sectionTransOffsetY+'px'
          })
          destTransOffsetY = _sectionTransOffsetY;
        } else {
          _transDir = 1;
          $inSection.css({
            'top': _sectionTransOffsetY+'px'
          })
          destTransOffsetY = -_sectionTransOffsetY;
        }
        
        // animate bg color box
        if (_bgBoxMouseMove != null)
          _bgBoxMouseMove.deactivate();
          
        boxDestX = (_transDir > 0) ? _w + (2 * _w) : -2 * _w;
        $bgBox.animate({left:boxDestX}, 600, "easeInExpo");
        
        // transition out the section we're leaving
        $outSection.animate({opacity:0.6, top:destTransOffsetY*0.5}, 650, "easeInExpo", function () {
          
          _transSectionIn();
          
          $outSection.animate({opacity: 0, top:destTransOffsetY}, 200, "easeOutExpo", function () {
            $outSection.addClass('hidden');
            
            // fade in next section tab once section is out
            $nextSectionTab.addClass(_curSectionId);
            $nextSectionTab.animate({opacity:1}, 450, 'easeOutQuad', function() { _sectionTabPulse.start(); });
            
          });
                    
        });

      } else {
        
        _transDir = 1;
        $bgBox.css({
          left:-2 * _w
        });
        _transSectionIn();
                
      }
                
    }
    
    // ----------------------------------------------------------------
    
    function _transSectionIn() {
      
      var $inSection = $('#'+_curSectionId),
          $outSection = $('section.out');      
      
      _transInTimeout = null;
      
      if ($outSection.length > 0) {
        $outSection.removeClass('out');
        $bgBox
          .removeClass($outSection.data('bg-color'))
          .removeClass($outSection.data('bg-skew'));
      }
      
      $bgBox
        .addClass($inSection.data('bg-color'))
        .addClass($inSection.data('bg-skew'))
        .css({ left:_transDir * (2 * -_w) })
        .animate({
          left:_w * 0.5 - (2 * _w),
          top: -((1.25 * _h) - _h) * 0.5
        }, 700, "easeOutExpo");
      
      $inSection
        .removeClass('hidden')
        .animate({opacity:1, top:0}, 700, "easeOutExpo", _transSectionInComplete);
      
    }
    
    // ----------------------------------------------------------------
    
    function _transSectionInComplete() {
      
      // reset flags
      _deltaOffset = 0;              
      _isTransitioningSections = false;
      
      if (_bgBoxMouseMove !== null)
        _bgBoxMouseMove.activate();
                      
      // if section navigation was queued during transition clear the queue and move on to the queued section
      if (_queuedSectionId !== null) {
        
        var destSection = _queuedSectionId;
        _queuedSectionId = null;
        _setSection(destSection);
                   
      } else {
        
        // update nextSectionTab link
        var $nextSection = $sections.eq(_sectionIndexes[_curSectionId] + 1);
        if ($nextSection.length > 0) {
          $nextSectionTab.attr('href', '#/'+$nextSection.attr('id'));
        }
        
        if (_backForthNavTimeout !== null) {
          clearTimeout(_backForthNavTimeout);
          _backForthNavTimeout= null;
        }
        
        _backForthNavTimeout = setTimeout(function() { 
            _isBackForthNavActive = true; 
            _checkBackForthNav();
          },
          1000
        );
                  
      }
      
    }
    
    // ----------------------------------------------------------------
    
    function _updateBackForth() {
      
      if (!_isMouseFollowActive) {
        return;
      }
      
      var direction = 0,
          nextSectionIndex = 0,
          isDirectionOverrideUpdate = false;
          
      if (_mousePos.y > _centerPos.y) {
        direction = 1;
      } else {
        direction = -1;
      }
              
      nextSectionIndex = _sectionIndexes[_curSectionId] + direction;
      
      // see if we need to override direction when we cant go forward or backward to another section any further
      if (nextSectionIndex < 0 && direction === -1) {
        isDirectionOverrideUpdate = (direction !== _directionOverride);
        _directionOverride = direction;
        direction = 1;
      } else if (nextSectionIndex >= $sections.length && direction === 1) {
        isDirectionOverrideUpdate = (direction !== _directionOverride);
        _directionOverride = direction;
        direction = -1;
      } else {
        if (_directionOverride != null) {
          // removing DirectionOverride
          $mouseFollower.stop()
          if ($mouseFollower.hasClass('hidden')) {
            $mouseFollower.removeClass('hidden');
          }
          $mouseFollower.animate({opacity:1}, 250, "easeOutQuad");
        }
        _directionOverride = null;
      }
      
      if (isDirectionOverrideUpdate) {
        //just doing the override for the "forth" direction when there are no further sections (ie: connect section)
        if (_directionOverride === 1) {
          $mouseFollower.animate({opacity:0}, 250, "easeOutQuad", function(){ $mouseFollower.addClass('hidden') });
        }
      }
      
      // do nothing if trying to set to the current direction
      if (direction == _backForthDir) {
        return;
      }
      
      // go ahead and swap directions
      _backForthDir = direction;
      
      $mouseFollower.stop()
      if ($mouseFollower.hasClass('hidden')) {
        $mouseFollower.removeClass('hidden');
      }
      $mouseFollower.animate({opacity:0}, 250, "easeOutQuad", function(){
        _backForthOffsetY = _backForthDir * Math.abs(_backForthOffsetY);
        
        var outClass = (_backForthDir > 0) ? "back" : "forth",
            inClass = (_backForthDir > 0) ? "forth" : "back";
            
        if ($mouseFollower.hasClass(outClass)) {
          $mouseFollower.removeClass(outClass);
        }
               
        $mouseFollower.addClass(inClass);
        
        // dont fade back in when overriding the "forth" direction
        if (isDirectionOverrideUpdate && _directionOverride === 1) {
          return;
        }
        
        $mouseFollower.animate({opacity:1}, 250, "easeOutQuad");
      });
      
    }
    
    // ----------------------------------------------------------------
    
    function _animate() {
  		requestAnimationFrame( _animate );
  		
  		if (_isMouseFollowActive) {
  	  	// update mouse follower position
    		_mFollowPos.x = _mFollowPos.x + (_mousePos.x - _mFollowPos.x) * 0.04;
    		_mFollowPos.y = _mFollowPos.y + (_mousePos.y - _mFollowPos.y) * 0.08;
  		    		  
    		$mouseFollower.css({
    		  top:_mFollowPos.y + _backForthOffsetY,
    		  left:_mFollowPos.x + _backForthOffsetX
    		});
  		}
  		
		}
		
		// ----------------------------------------------------------------
		
		function _onResize() {
		  _w = $wrapper.outerWidth();
		  _h = $wrapper.outerHeight();
		  
		  _centerPos.x = _w * 0.5;
		  _centerPos.y = _h * 0.5;
		  
		  _forthThresholdY = _h - _backForthMargin;
		  
		  if (!_isTransitioningSections){
		    $bgBox.css({
  		    width: 2 * _w,
  		    height: 1.25 * _h,
  		    top: -((1.25 * _h) - _h) * 0.5,
  		    left: _w * 0.5 - (2 * _w)
  		  });
  		  
  		  
		  }
		  
		  if (_bgBoxMouseMove !== null)
		    _bgBoxMouseMove.setBounds(0, 0, _w, _h); 
		}
		
		function _updateOrientation(e) {
		  _
		}
    
    // ----------------------------------------------------------------
    // ----------------------------------------------------------------
    
    _init();
    
    return {};
    
  };
  
  // ====================================================================
  // @MouseRangeMovementItem plugin
  // ====================================================================
  var MouseRangeMovementItem = function(options, elem) {
    
    var $this = $(elem),
        $body = $('body'),
    		_movementRadiusX = options.movementSizeX * 0.5,
				_movementRadiusY = options.movementSizeY * 0.5,
				_initX = 0,
				_initY = 0,
				_mousePos = {x: 0, y: 0},
				_mouseDelayPos = {x: 0, y: 0},
				_hasMouseMoved = false,
				_rangeX = null,
				_rangeY = null,
				_boundsX = null,
				_boundsY = null,
				_isActive = false,
				_hasMouseMoved = false,
				firstTrace = true;
    
    // ----------------------------------------------------------------
    
    function _init() {
      
      var $win= $(window);
      _boundsX = range(0, $win.width());
      _boundsY = range(0, $win.height());

    }; // _init()
    
    function _activate() {
      
      _isActive = true;
      
      _initX = parseInt($this.css('left').split('px')[0], 10);
			_initY = parseInt($this.css('top').split('px')[0], 10);
	    	    
      _rangeX = range(_initX + _movementRadiusX, _initX - _movementRadiusX);
      _rangeY = range(_initY + _movementRadiusY, _initY - _movementRadiusY);
            
      $body.bind('mousemove', _onMouseMove);
      
      firstTrace = true;
    }
    
    // ----------------------------------------------------------------
    
    function _deactivate() {

      _isActive = false;

      $body.unbind('mousemove', _onMouseMove);

      _hasMouseMoved = false;
      
    }
    
    // ----------------------------------------------------------------
    
    function _onMouseMove(e) {
      
      _mousePos.x = e.pageX;
      _mousePos.y = e.pageY;
      
      if (!_hasMouseMoved) {
        _mouseDelayPos.x = _boundsX.getValueOfPercent(0.5);
        _mouseDelayPos.y = _boundsY.getValueOfPercent(0.5);
        _hasMouseMoved = true;
        _animate();
      }
      
    }
    
    // ----------------------------------------------------------------
    
    function _animate() {
      
      if (!_isActive) {
        return;
      }
            
      // update mouse dest position
  		_mouseDelayPos.x = _mouseDelayPos.x + (_mousePos.x - _mouseDelayPos.x) * 0.1;
  		_mouseDelayPos.y = _mouseDelayPos.y + (_mousePos.y - _mouseDelayPos.y) * 0.1;
  		
  		var destPctX = _boundsX.getPercentOfValue(_mouseDelayPos.x),
  		    destPctY = _boundsY.getPercentOfValue(_mouseDelayPos.y),
  		    x = _rangeX.getValueOfPercent(destPctX),
					y = _rangeY.getValueOfPercent(destPctY);
						
			$this.css({
				left: x,
				top: y
			});
  		
  		requestAnimationFrame( _animate );
      
    }
    
    // ----------------------------------------------------------------
    
    _init();
    
    return {
	    
	    activate : function () {
	      _activate();	      
	    },
	    
	    deactivate: function() {
	      _deactivate();	      
	    },
	    
      setBounds: function(x1, y1, x2, y2) {

				_boundsX = range(x1, x2);
        _boundsY = range(y1, y2);
        
			}
    };
    
  };
  
  // ==================================================================
  
  $.fn.mouseRangeMovementItem = function(options) {
    
    var pluginName = "MouseRangeMovementItem";
    
    options = $.extend({}, $.fn.mouseRangeMovementItem.defaults, options);
    
    return this.each(function(){
      
      var $this = $(this);
      
      if($this.data(pluginName)) {
        return;
      }
      
      // No JavaScript plugin instance exists, so add it as data attribute.
      var pluginInstance = new MouseRangeMovementItem(options, this);
      $this.data(pluginName, pluginInstance);
      
    });
    
  };
  
  // ==================================================================
  
  $.fn.mouseRangeMovementItem.defaults = {
    movementSizeX: 10,
		movementSizeY: 10
  };
  
  var Pulse = function(outAlpha, elem) {
    
    var $this = $(elem),
        _outAlpha = outAlpha,
        _repeatDelay = 100,
        _repeatTimeout = null;
    
    function _pulseOut() {
      _repeatTimeout = null;
      $this.stop().animate({opacity:_outAlpha}, 800, "easeInOutQuad", _pulseIn);
    }
    
    function _pulseIn() {
       $this.stop().animate({opacity:1}, 600, "easeInOutQuad", _repeat);
    }
    
    function _repeat() {
      //_repeatTimeout = setTimeout(_pulseOut, _repeatDelay);
      _pulseOut();
    }

    // ----------------------------------------------------------------
    // ----------------------------------------------------------------
    
    return {
      start: function() {
        _pulseOut();
      },
      
      stop: function(fadeIn) {
        $this.stop();
        
        if (_repeatTimeout != null) {
          clearTimeout(_repeatTimeout);
          _repeatTimeout = null;
        }
        
        if (fadeIn === true) {
          $this.animate({opacity:1}, 500);
        }
      }
    }
  };
  
  $.fn.pulse = function (outAlpha) {
    
    var pluginName = "Pulse";
    
    return this.each(function () {
      
      var $this = $(this);
      
      if($this.data(pluginName)) {
        return;
      }
      
      var pluginInstance = new Pulse(outAlpha, this);
      $this.data(pluginName, pluginInstance);
      
    });
    
  };
  
  var TouchSwipe = function(options, elem) {
    
    var $this = $(elem),
				_orientation = options.orientation,
        _touchStartX = -1,
				_touchStartY = -1,
				_currTouchID = false,
        _isMoving = false;
							    		
    // ----------------------------------------------------------------
    
    function _init() {

			$this.bind('touchstart.touchswipe', _onTouchStart);
      $this.bind('touchend.touchswipe', _onTouchEnd);
			
    }; // _init()
		
	 function _onTouchStart(event) {
      // See if we've got a touch already.
      var e = event.originalEvent;
      if(_currTouchID === false) {
        e.preventDefault();
				
        var touch = e.targetTouches[0];
        _currTouchID = touch.identifier;        
        _touchStartX = touch.pageX;
				_touchStartY = touch.pageY;
				
				_isMoving = true;
				$this.bind('touchmove.touchswipe', _onTouchMove);
      }
    };

    function _onTouchMove(event) {
      var e = event.originalEvent;
      if(_currTouchID !== false) {
        // Find the location of this touch.
        var touch = null,
            numTouches = e.changedTouches.length;
        for(var i = 0; i < numTouches; i++) {
          if(e.changedTouches[i].identifier == _currTouchID) {
            touch = e.changedTouches[i];
            break;
          }
        }

        if(touch != null) {
          // Get the diff.
          e.preventDefault();
					var touchX = touch.pageX;
					var touchY = touch.pageY;
          var diffX = touchX - _touchStartX;
					var diffY = touchY - _touchStartY;
          					
					if (_orientation == "horizontal") {
						if(Math.abs(diffX) >= options.min_move) {
							_cancelTouch();
              if(diffX > 0) {
                options.swipeLeft();
              } else {
                options.swipeRight();
              }
						}
					} else if (_orientation == "vertical") {
						if(Math.abs(diffY) >= options.min_move) {
							_cancelTouch();
              if(diffY > 0) {
                options.swipeDown();
              } else {
                options.swipeUp();
              }
						}
					}
				
        }
      }
    };
		
		function _onTouchEnd(event) {
      var e = event.originalEvent;
      if(_currTouchID !== false) {
        // Find the location of this touch.
        var touch = null,
            numTouches = e.changedTouches.length;
        for(var i = 0; i < numTouches; i++) {
          if(e.changedTouches[i].identifier == _currTouchID) {
            touch = e.changedTouches[i];
            break;
          }
        }

        if(touch != null) {
          e.preventDefault();
					_cancelTouch();
        }
      }
    };

		function _cancelTouch() {
			_currTouchID = false;
      _touchStartX = -1;
			_touchStartY = -1;
			_isMoving = false;
			$this.unbind('touchmove.touchswipe', _onTouchMove);
		}

    // ----------------------------------------------------------------
    
    _init();
    
    return {
      updateOrientation: function(orientation) {
				_orientation = orientation;
			}
    };
    
  };
  
  // ==================================================================
  
  $.fn.touchSwipe = function(options) {
    
    var pluginName = "TouchSwipe";
    
    options = $.extend({}, $.fn.touchSwipe.defaults, options);
    
    return this.each(function(){
      
      var $this = $(this);
      
      if($this.data(pluginName)) {
        return;
      }
      
      // No JavaScript plugin instance exists, so add it as data attribute.
      var pluginInstance = new TouchSwipe(options, this);
      $this.data(pluginName, pluginInstance);
      
    });
    
  };
  
  // ==================================================================
  
  $.fn.touchSwipe.defaults = {
		orientation:'horizontal',
    min_move: 20,
	  swipeLeft: function() { alert("left"); },
		swipeRight: function() { alert("right"); },
		swipeUp: function() { alert("up"); },
		swipeDown: function() { alert("down"); }
  };
	
	
})(jQuery);


jQuery(function() {

  // dom ready
  TS.site = TS.initialize();
  
});

