(function($){  
  
  $.fn.reverseOrder = function() {
  	return this.each(function() {
  		$(this).prependTo($(this).parent());
    });
  };
  
  $.fn.fadeInOver = function(activeSel, callback) {
    var current = this.children('.section.active').eq(0);
    var newActive = this.children(activeSel).eq(0);
                
    if (current.attr('id') != newActive.attr('id')) {
      this.children('.section').not(current, newActive).each(function() {
        $(this).css({ zIndex: 0 }).hide();
      });
      
      newActive.hide().css({ zIndex: 1000 });
      current.css({ zIndex: 500 }).removeClass('active');
      newActive.fadeIn(800, function() {
        if($.isFunction(callback)) callback.apply(this, [newActive, current]);
      }).addClass('active');
    } else if($.isFunction(callback)) {
      callback.apply(this, [newActive, current]);
    }
    
    return this;
  };

  $.fn.shuffle = function() {
    return this.each(function(){
      var items = $(this).children();
      return (items.length) ? $(this).html($.shuffle(items)) : this;
    });
  }

  $.shuffle = function(arr) {
    for (var j, x, i = arr.length; i;
      j = parseInt(Math.random() * i),
      x = arr[--i], arr[i] = arr[j], arr[j] = x
    );
    return arr;
  }
  
})(jQuery);

var ProjectHelpers = function(app) {
  
  this.helpers({
    
    info: function(prefix, str) {
      if (this.app.section && this.app.section.element) {
        var infoElem = this.app.section.element.find('.info');
        if (prefix == null && str == null) {
          infoElem.empty();
        } else {
          infoElem.html(prefix ? ('<strong>' + prefix + '</strong>') : '');
          if (str) infoElem.append(str);
        }
      }
    },
    
    hasOverlay: function() {
      return (this.app.section && this.app.section.element.hasClass('hasOverlay'));
    },
    
    withSection: function(sectionId, callback) {
      var sectionId = this.params['section'];
      var section = null;
      var self = this;
      
      if (section = this.app.sections[sectionId]) {
        var changed = this.app.section == null || this.app.section.id != sectionId;
        this.app.section = section;
        this.app.pager   = section.pager;
        
        var hasNav = section.element.hasClass('nav');        
        hasNav ? $('#navigation').hide() : $('#navigation').show();
        
        $('#sections').fadeInOver('#' + section.id, function(active, previous) {
          if (changed && previous != null && active != previous) {
            previous.children('.overlay').show();
            previous.addClass('hasOverlay');
            previous.hide();
          }
          
          $('body').attr('id', 'section-' + section.id); // first
          self.title(section.title || sectionId.toUpperCase());
          if ($.isFunction(callback)) callback.apply(self, [section]);
          if (changed) self.trigger('section-changed', section);
        });
      } else {
        this.redirect('');
      }
    },
    
    seekToId: function(id) {
      var pagerIdx = this.app.pager.getIndex();
      var items    = this.app.pager.getItems();
      var item     = items.filter('#' + id)[0];
      var idx      = $.inArray(item, items);
      var lastIdx  = items.length - 1;
      
      if (idx == -1) return null;
      
      if (idx != pagerIdx) {
        if (pagerIdx == 0 && idx == lastIdx) {
          this.app.pager.move(-1); // circular, prev
        } else if (pagerIdx == lastIdx && idx == 0) {
          this.app.pager.move(1); // circular, next
        } else if (idx < pagerIdx) {
          this.app.pager.move(-(pagerIdx - idx));           
        } else if (idx > pagerIdx) {
          this.app.pager.move(idx - pagerIdx);
        }
      }
      
      return $(item);
    },
    
    pagePrev: function() {
      var items = this.app.pager.getItems();   
      var lastIdx = items.length - 1;
      var idx = this.app.pager.getIndex();
      idx = (idx == 0) ? lastIdx : idx - 1;
      var item = items.eq(idx);
      if (this.app.section && item && item.attr('id')) {
        this.app.setLocation('#/' + this.app.section.id + '/' + item.attr('id'));
      }
    },
    
    pageNext: function() {
      var items = this.app.pager.getItems();   
      var lastIdx = items.length - 1;
      var idx = this.app.pager.getIndex();
      idx = (idx >= lastIdx) ? idx = 0 : idx + 1;
      var item = items.eq(idx);
      if (this.app.section && item && item.attr('id')) {
        this.app.setLocation('#/' + this.app.section.id + '/' + item.attr('id'));
      }
    }

  });
  
  this.bind('prev', function() {
    this.pagePrev();
  });

  this.bind('next', function() {
    this.pageNext();
  });

  this.bind('home', function() {
    this.app.setLocation('#/main/index');
  });
  
  this.bind('navigate', function(e, elem) {
    // bind to section specific navigation
    if (this.app.section && this.app.section.nav) {
      var callback = this.app.section.nav[elem];
      if ($.isFunction(callback)) callback.apply(this, [this]);
    }
  });
  
  this.bind('seek', function(evt, hsh) {
    var self  = this;
    var items = this.app.pager.getItems();
    var item  = items[this.app.pager.getIndex()];
    if (item) {
      $('#container').attr('class', 'page-' + this.app.section.id + '-' + $(item).attr('id'));
      this.info(this.app.section.prefix, $(item).attr('title'));
      if ($(item).hasClass('autotoggle')) {
        setTimeout(function() { self.trigger('overlay', { show: false }); }, this.app.section.delay || 500);
      }
    }
  });
  
  this.bind('toggle', function(e, options) {
    this.trigger('overlay', $.extend(options, { show: !this.hasOverlay() }));
  });
  
  this.bind('fadeIn', function() {
    if(!this.hasOverlay() && this.app.section && this.app.section.info) {
      this.app.section.element.find('.fade').fadeIn();
      $('.switch').addClass('highlight');
    }
  });
  
  this.bind('fadeOut', function() {
    if(!this.hasOverlay() && this.app.section && this.app.section.info) {
      this.app.section.element.find('.fade').fadeOut();
    }
    $('.switch').removeClass('highlight');
  });

  this.bind('toggleUI', function(e, options) {
    var show = options['show'];
    var context = this;
    
    var callback = options['callback'];
    if (!$.isFunction(callback)) callback = $.noop;
    
    var valid = context.app.section && context.app.section.element;
    var items = valid ? context.app.section.element.children('.info') : $();
    var toggleUI = valid && context.app.section.toggleUI;
    
    if (toggleUI && items.has('*')) {
      if (show && context.app.section.info) {
        items.fadeIn(400, function() {
          if (this == items.last()[0]) callback.apply(context, [context]);
        });
      } else {
        items.fadeOut(400, function() {
          if (this == items.last()[0]) callback.apply(context, [context]);
        });
      }
    } else {
      callback.apply(context, [context]);
    }
  });

  this.bind('overlay', function(e, options) {
    var show = options['show'];
    var context = this;
    
    var callback = options['callback'];
    if (!$.isFunction(callback)) callback = $.noop;
    
    if (this.app.section && this.app.section.element) {
      var overlay = this.app.section.element.children('.overlay');
      var hasOverlay = this.app.section.element.hasClass('hasOverlay');
      
      if (show && !hasOverlay) {
        overlay.fadeIn(400, function() {
          context.trigger('toggleUI', options);
          context.app.section.element.addClass('hasOverlay');
        });
      } else if (!show && hasOverlay) {
        context.trigger('toggleUI', $.extend(options, { callback: function() {
          overlay.fadeOut(400, function() {
            callback.apply(context, [context]);
            context.app.section.element.removeClass('hasOverlay');
          });
        }}));
      } else {
        callback.apply(context, [context]);
      }
    }
  });
  
};

