// The Golden Rule
var $j = jQuery.noConflict();

(function($){
  $.extend($.expr[':'],{
    readonly: function(a) {
      return !!a.readOnly;
    }
  });
})(jQuery);

/* Layer takes any element, passed to it as a selector (content), and renders it 
 * in a "layer" that is positioned relative to its containing elment (trigger).
 */
(function($){
  
  $.layer = {
    blocked: false,
    defaults: {
      animate: false,
      // id: 'Layer',
      placement: 'above',
      trigger: null
    },
    block: function() {
      $.layer.blocked = !$.layer.blocked;
    }
  }
  
  $.fn.extend({
    layer: function(options) {
      opts = $.extend({}, $.layer.defaults, options);
      $(document).ready(function() { insertLayer(opts); });
      return this.each(function() {
        var onShow = opts.onShow || function (){};
        $.data(this, 'layer', opts)
        // console.log($(this).data('layer'))
      })
      .click(handleClick);
    },
    display: function(elem) {
      $(this).appendTo(opts.layer)
      opts.layer
        .find(':first-child')
          .show()
        .end()
          .css({
            position: 'absolute',
            top: getMetrics(elem).top+'px',
            left: getMetrics(elem).left+'px'
          });
      (opts.animate) ? opts.layer.show('blind', 500) : opts.layer.show();
      $.layer.block();
      $(document).click(listenForHide);
      if ($.browser.msie && $.browser.version.substr(0,1) == 6)
        $('select:not(".layer select")').hide();
      if ($.data(elem, 'layer').onShow)
        $.data(elem, 'layer').onShow(opts.layer);
    },
    undisplay: function() {
      var content = opts.layer.children().eq(0).attr('id');
      var link    = $('a[href="#'+content+'"]');
      link.after($('#'+content).hide());
      opts.layer.hide();
      if ($.browser.msie && $.browser.version.substr(0,1) == 6)
        $('select:not(".layer select")').show();
      $(document).unbind('click', listenForHide);
    }
  })
  
  function insertLayer(opts) {
    opts.layer = $('<div class="layer"></div>').appendTo(document.body).hide();
    // opts.layer = $('<div id="'+opts.id+'" class="layer"></div>').appendTo(document.body).hide();
  }
  
  function getMetrics(elem) {
    $(elem).css('position', 'relative');
    return {
      top: ($(elem).data('layer').placement == 'above') ? $(elem).offset().top -= opts.layer.height() : $(elem).offset().top += $(elem).height(),
      left: $(elem).offset().left -= 5
    }
  }
  
  function handleClick(e) {
    if (e) e.preventDefault();
    if ($.layer.blocked) return;
    if (opts.layer.css('display') == 'block') $(opts.trigger).undisplay();
    
    var selector = $(this).data('layer').content || $(this).attr('href');
    opts.trigger = this;
    $(this)
      .next(selector)
        .display(this)
  }
  
  function listenForHide(e) {
    if (!$.layer.blocked) {
      if ($(e.target).parents('.layer').length == 0 && opts.layer.css('display') == 'block') {
        opts.layer.undisplay();
      }
    } else {
      $.layer.block();
    }
  }
    
})(jQuery);

// Favorites
(function($){
  
  $.favorites = {
    getFavs: function() {
      doAjax('get', 'index');
      // $('a.favorite').removeClass('remove-fav');
      // $.getJSON('/ajax/favorites.json', { method:'index' }, function(data) {
      //   $(data).each(function(i, node) {
      //     // console.info(node.item_id+'\n'+$('li[data-cakeid="'+node.item_id+'"]'))
      //     $('li[data-cakeid="'+node.item_id+'"] a.favorite').addClass('remove-fav').removeClass('add-fav');
      //   })
      // })
    }
  }
  
  $.fn.extend({
    favorites: function(options) {
      var opts = $.extend({}, options);
      if ($.cookie('registered_user') == 'true') $.favorites.getFavs();
      return this.click(handleClick);
    }
  })
  
  function handleClick(e) {
    var t = $(this);
    var cakeId = t.closest('li').attr('data-cakeid') || $('#cake_id').val();
    var method = (!t.hasClass('added')) ? 'create' : 'delete';
    doAjax('post', method, cakeId);
    
    try {
      var pageTracker = _gat._getTracker("UA-8529536-1");
      var pageURL = (method == 'create') ? '/favorite-this-cake' : '/unfavorite-this-cake';
      pageTracker._trackPageview(pageURL);
    } catch(err) {}
    
    return false;
  }
  
  function doAjax(type, method, cakeId) {
    var dt = (!cakeId) ? 'json' : 'text';
    $.ajax({
      type: type,
      url: "/ajax/favorites.json",
      data: {
        _method: method,
        id: cakeId
      },
      dataType: dt,
      success: function(data, textStatus) {
        if (cakeId) {
          if (method == 'create') {
            $('li[data-cakeid="'+cakeId+'"] a.favorite').addClass('added');
            if ($('#cake_id').length > 0) $('p[data-cakeid="'+cakeId+'"] a.favorite').addClass('added').text('Remove from Favorites');
          } else {
            $('li[data-cakeid="'+cakeId+'"] a.favorite').removeClass('added');
            if ($('#cake_id').length > 0) $('p[data-cakeid="'+cakeId+'"] a.favorite').removeClass('added').text('Make it a Favorite');
          }
        } else {
          $('a.favorite').removeClass('added');
          $(data).each(function(i, node) {
            $('li[data-cakeid="'+node.item_id+'"] a.favorite').addClass('added');
            $('p[data-cakeid="'+node.item_id+'"] a.favorite').addClass('added').text('Remove from Favorites');
          });
        }
      },
      error: function(data, textStatus) {        
        if (data.status == 412)
          $.fn.statusMessage('You must sign-in to use this feature.');
      }
    });
  }
  
})(jQuery);

(function($){
  
  $.imgProcess = {
    count: 0,
    firstRun: true
  }
  
  $.fn.extend({
    imgProcess: function(options) {
      var options = $.extend({}, $.imgProcess, options);
      
      return this.each(function(i, el) {
        var obj = $(this);
        var slides = obj.find('a');
        
        slides.eq(0).css({
          display: 'block',
          opacity: 1.0
        });
        
        if (slides.length <= 1) return;
        
        var to = window.setInterval(function() {
          crossFade(slides, options);
        }, 3000);
      });    
    }
  });
  function crossFade(slides, options) {
    if (options.firstRun) {
      slides.eq(1).css('display', 'block');
      options.firstRun = false;
    }
    current = slides.eq(options.count);
    slides
      .eq(options.count)
        .animate({ opacity: 0.0 }, 1000, function(){ current.css('display', 'none') });
    (options.count < slides.length-1) ? options.count++ : options.count = 0;
    slides
      .eq(options.count)
        .css('display', 'block')
          .animate({ opacity: 1.0 }, 1000);
  };
  
})(jQuery);

// Events page
(function($){
  
  $.eventsControl = {
    defaults: {
      eventsObj: []
    }
  };
  
  $.fn.extend({
    eventsControl: function(options) {
      var options = $.extend({}, $.eventsControl.defaults, options);
      return this.each(function() {
        $.data(this, 'event', options);
        el = $(this);
        options.sel         = el.find('select#fbEventName');
        options.checkBox    = el.find('input:checkbox');
        options.eventName   = el.find('#event_name');
        options.createForm  = el.find('#CreateEvent');
        options.sel.bind('change', options, selectChange);
        options.checkBox.bind('change', options, checkboxChange);
      });
    }
  });
  
  function selectChange(e) {
    if (this.value == "false") {
      e.data.createForm
        .find(':readonly')
          .removeAttr('readonly')
            .val('');
      $('.ui-datepicker-trigger:first').show();
    } else {
      var fbId = this.value;
      var eventData = $.grep(e.data.eventsObj, function(obj, i) {
        // Get data for facebook event id
        return obj.eid == fbId;
      });
            
      // Set details for new cake event based on facebook event data
      e.data.eventName
        .attr('readonly', 'readonly')
          .val(eventData[0].name);
      e.data.checkBox.each(function(i, el) {
        
        // Get data for current form input from currently selected event
        var newVal = eventData[0][this.value];
        
        // Format if current input is date
        if (this.name == 'event_event_date') {
          newVal = $.datepicker.formatDate('MM d, yy', new Date(newVal * 1000));
          $('.ui-datepicker-trigger:first').hide();
        }
        
        // Set corresponding form input in create new event form, disable input
        e.data.createForm
          .find('#' + this.name)
            .attr('readonly', 'readonly')
              .val( el.checked ? newVal : '' );
      });
    }
  }
    
  function checkboxChange(e) {
    var fbId = $('#FbEventName').val();
    if (fbId != 'false') {
      var el = e.data.createForm.find('#' + this.name);
      var eventData = $.grep(e.data.eventsObj, function(obj, i) {
        // Get event data for facebook event id
        return obj.eid == fbId;
      });
      el.val( this.checked ? eventData[0][this.value] : '' );
    }
  }
  
})(jQuery);

// Utility functions
(function($){
  
  $.fn.truncate = function(txt, length, truncation) {
    length = length || 30;
    truncation = (truncation == undefined) ? '...' : truncation;
    return txt.length > length ?
      txt.slice(0, length - truncation.length) + truncation : String(txt);
  };
  
  // Use this for collapsible panes (not chainable)
  $.fn.toggleable = function(e) {
    var me = $(e.target);
    var t = (me.hasClass('.trigger') ? me : me.closest('.trigger'));
    (t.hasClass('open')) ? t.removeClass('open').next().hide() : t.addClass('open').next().show();
    return false;
  };
  
  // Creates a status message at the top of the page, similar to rails flash:notice method (not chainable)
  $.fn.statusMessage = function(content) {
    var statusmsg = '<div id="StatusMessage"><p>'+content+'</p></div>';
    if ($('#StatusMessage').length == 0) $('body').prepend(statusmsg);
    window.scrollTo(0,0);
    var clear = setTimeout(function() {
      $('#StatusMessage').slideUp(1000, onFinish);
      clearTimeout(clear);
    }, 4000);
    function onFinish() {
      $(this).remove();
    }
  };
  
  $.fn.registered = function(bool) {
    $.cookie('registered_user', bool, { path:'/' });
  };
  
  // Use this to set consistent heights on floated list elements (chainable)
  $.fn.extend({
    doHeights: function(sel) {
      var h = 0;
      return $(this).find('li').each(function(i, el) {
        if ($(el).outerHeight() > h) h = $(el).outerHeight();
      }).height(h);
    }
  });
  
  $(window).load(function(){
    if ($('a.favorite').length > 0) $('a.favorite').favorites();
    if ($('ul.selections').length > 0) $('ul.selections:visible').doHeights();
    if ($('.category-list').length > 0) {
      var cname = $('.category-list').prev('h3').text();
      $('.category-list').treeview({
        collapsed:true,
        persist:'cookie',
        cookieId:cname
      });
    }
  });
    
})(jQuery);

String.prototype.capitalize = function(){ //v1.0
    return this.replace(/\w+/g, function(a){
        return a.charAt(0).toUpperCase() + a.substr(1).toLowerCase();
    });
};

// TEMPORARY HOME FOR NON-FIREBUG CONSOLE LOGGING, CAN REMOVE FOR PRODUCTION
if (!window.console){ // CONSOLE LOGGING FOR IE
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i=0; i<names.length; ++i) window.console[names[i]] = function(){}
};