/*
 * 	Snapple Facebook Fanpage Wall 1.0 - jQuery plugin
 *	written by Mike Fey (Hello Monday)	
 *	http://hellomonday.com
 *
 *	Built for jQuery library
 *	http://jquery.com
 *
 *  uses date functions written by Matt Kruse (http://www.javascripttoolbox.com/lib/date/source.php)
 *
 *  CSS classes created (for custom styling):
 *
 * 	post container: .fbFeedPost 
 * 	profile pic: .fbPostProfilePic
 * 	date: .fbPostDate
 * 	post author: .fbPostFrom
 * 	post content: .fbPostContent
 *  "likes": .fbLikesContainer
 *
 */

 (function($) {

  var methods = {

    init: function(options) {
      return this.each(function() {

        // default configuration properties
        var defaults = {
          facebookId: 'snapple', //the string id of the facebook page, i.e. facebook.com/snapple
          showDate: 'false', //show the post date
          showLikes: 'false', //show the post likes
          animate: 'false', //automatically scroll the posts
          animateSpeed: 3000, //how fast to automatically scroll the posts
          maxStatuses: 200, //how many statuses to retrieve from the api
          viewed: false //whether the plugin has already been initialized
        };

        var opts = $.extend(defaults, options);
        var containerDiv = $(this);
        var obArray = [];
        var animateInt = 0;
        var jspapi;
        var animateTimeout = 0;
        var animateInterval = 0;
        var shouldScroll = true;
        var curBrowser = navigator.userAgent.toLowerCase();
        
				//if the plugin has not been initialized yet, get the content through a JSON
				//call
        if (opts.viewed == false) {
          
					//this is a div that is spit out in the PHP, containing the Facebook
					//access token 
          var at = $('#fbAccessToken').html();
          at = at.substr(13, at.length);

          $.getJSON("https://graph.facebook.com/snapple/feed?access_token=" + at + "&limit=" + opts.maxStatuses + "&callback=?",
          function(json) {
            $.each(json.data,
            function(i, fb) {
            	if (fb.from.name.toLowerCase() == 'snapple') {
        		  obArray.push(fb);
        		}
            });
            layoutFeed();
          });
        } else {
					//if the plugin has already been initialized, restart the animations
          if (opts.animate == 'true') {

            startScrollAnimation();

            containerDiv.scroll(function() {
              if (shouldScroll == true) {
                clearInterval(animateInterval);
                clearTimeout(animateTimeout);
                animateTimeout = setTimeout(startScrollAnimation, 5000);
                containerDiv.data('animateTimeout', animateTimeout);
              }
            });

            containerDiv.find('.jspContainer').bind('mousewheel',
            function(event, delta) {
              shouldScroll = false;
              clearInterval(animateInterval);
              clearTimeout(animateTimeout);
            });

            containerDiv.find('.jspDrag').bind('mousedown',
            function() {
              shouldScroll = false;
              clearInterval(animateInterval);
              clearTimeout(animateTimeout);
            });
          }
        }
        
				//lays out all of the graphic elements in the module container
        function layoutFeed() {
          var feedStr = '';

          for (var i = 0; i < obArray.length; i++) {
            feedStr += '<div class="fbFeedPost">';
            feedStr += '<div class="fbPostProfilePic"><img src="http://graph.facebook.com/' + obArray[i].from.id + '/picture" width="35" height="35"/></div>';
            if (opts.showDate == 'true') {
              var pd = new Date(obArray[i].created_time);
              feedStr += '<div class="fbPostDate">' + formatDate(pd, 'MMM dd, yyyy hh:mma') + '</div>';
            }

            feedStr += '<div class="fbPostFrom">' + obArray[i].from.name + '</div>';
            var msg = obArray[i].message;
            if (msg == undefined) {
              msg = '...'
            }
            feedStr += '<div class="fbPostContent">' + msg + '</div>';
            if (opts.showLikes == 'true') {
              if (obArray[i].likes != undefined) {
                feedStr += '<div class="fbPostLikes">';
                feedStr += '<div class="fbLikesContainer">';
                var lc = 0;
                for (var l = 0; l < obArray[i].likes.data.length; l++) {
                  lc++;
                  if (lc < obArray[i].likes.data.length - 1) {
                    feedStr += obArray[i].likes.data[l].name + ', ';
                  } else {
                    feedStr += obArray[i].likes.data[l].name + ' ';
                  }
                }

                if (lc > 2) {
                  feedStr += 'and ' + (obArray[i].likes.count - lc) + ' others like this</div></div>';
                } else {
                  feedStr += 'likes this</div></div>';
                }

              }
            }

            feedStr += '</div>';
          }

          containerDiv.html(feedStr);

          var trackBgColor = 'rgba(196, 198, 202, 0.75)';
          if (curBrowser.indexOf('msie 8.0') != -1) {
            trackBgColor = '#c4c6ca';
          }

          containerDiv.jScrollPane({
            verticalDragMinHeight: 35,
            animateScroll: true,
            trackColor: trackBgColor,
            draggerHeightOffset: 10
          });

          jspapi = containerDiv.data('jsp');

          if (opts.animate == 'true') {

            startScrollAnimation();

            containerDiv.scroll(function() {
              if (shouldScroll == true) {
                clearInterval(animateInterval);
                clearTimeout(animateTimeout);
                animateTimeout = setTimeout(startScrollAnimation, 5000);
                containerDiv.data('animateTimeout', animateTimeout);
              }
            });

            containerDiv.find('.jspContainer').bind('mousewheel',
            function(event, delta) {
              shouldScroll = false;
              clearInterval(animateInterval);
              clearTimeout(animateTimeout);
            });

            containerDiv.find('.jspDrag').bind('mousedown',
            function() {
              shouldScroll = false;
              clearInterval(animateInterval);
              clearTimeout(animateTimeout);
            });
          }

          containerDiv.css({
            opacity: 0.0
          });
          containerDiv.stop(true, true).animate({
            opacity: 1.0
          },
          {
            duration: 500,
            specialEasing: {
              opacity: 'easeOutSine'
            }
          });
        }
        
				//starts the statuses auto scrolling
        function startScrollAnimation() {
          animateInterval = setInterval(scrollStatuses, opts.animateSpeed);
          containerDiv.data('animateInterval', animateInterval);
        }
        
				//scrolls to the top of each status in order, on a timer
        function scrollStatuses() {
          jspapi = containerDiv.data('jsp');

          animateInt++;
          if (animateInt > opts.maxStatuses - 1) {
            animateInt = 0;
          }

          var curStat;

          $('.fbFeedPost').each(function(ind) {
            if (ind == animateInt) {
              curStat = $(this).position().top;
            }
          });

          jspapi.scrollToY(parseInt(curStat));
          return false;
        }

        //date conversion functions, taken from
				//http://www.mattkruse.com/javascript/date/source.html
        var MONTH_NAMES = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
        var DAY_NAMES = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
        function LZ(x) {
          return (x < 0 || x > 9 ? "": "0") + x
        }

        function isDate(val, format) {
          var date = getDateFromFormat(val, format);
          if (date == 0) {
            return false;
          }
          return true;
        }

        function compareDates(date1, dateformat1, date2, dateformat2) {
          var d1 = getDateFromFormat(date1, dateformat1);
          var d2 = getDateFromFormat(date2, dateformat2);
          if (d1 == 0 || d2 == 0) {
            return - 1;
          } else if (d1 > d2) {
            return 1;
          }
          return 0;
        }

        function formatDate(date, format) {
          format = format + "";
          var result = "";
          var i_format = 0;
          var c = "";
          var token = "";
          var y = date.getYear() + "";
          var M = date.getMonth() + 1;
          var d = date.getDate();
          var E = date.getDay();
          var H = date.getHours();
          var m = date.getMinutes();
          var s = date.getSeconds();
          var yyyy,
          yy,
          MMM,
          MM,
          dd,
          hh,
          h,
          mm,
          ss,
          ampm,
          HH,
          H,
          KK,
          K,
          kk,
          k;
          // Convert real date parts into formatted versions
          var value = new Object();
          if (y.length < 4) {
            y = "" + (y - 0 + 1900);
          }
          value["y"] = "" + y;
          value["yyyy"] = y;
          value["yy"] = y.substring(2, 4);
          value["M"] = M;
          value["MM"] = LZ(M);
          value["MMM"] = MONTH_NAMES[M - 1];
          value["NNN"] = MONTH_NAMES[M + 11];
          value["d"] = d;
          value["dd"] = LZ(d);
          value["E"] = DAY_NAMES[E + 7];
          value["EE"] = DAY_NAMES[E];
          value["H"] = H;
          value["HH"] = LZ(H);
          if (H == 0) {
            value["h"] = 12;
          }
          else if (H > 12) {
            value["h"] = H - 12;
          }
          else {
            value["h"] = H;
          }
          value["hh"] = LZ(value["h"]);
          if (H > 11) {
            value["K"] = H - 12;
          } else {
            value["K"] = H;
          }
          value["k"] = H + 1;
          value["KK"] = LZ(value["K"]);
          value["kk"] = LZ(value["k"]);
          if (H > 11) {
            value["a"] = "PM";
          }
          else {
            value["a"] = "AM";
          }
          value["m"] = m;
          value["mm"] = LZ(m);
          value["s"] = s;
          value["ss"] = LZ(s);
          while (i_format < format.length) {
            c = format.charAt(i_format);
            token = "";
            while ((format.charAt(i_format) == c) && (i_format < format.length)) {
              token += format.charAt(i_format++);
            }
            if (value[token] != null) {
              result = result + value[token];
            } else {
              result = result + token;
            }
          }
          return result;
        }

        function _isInteger(val) {
          var digits = "1234567890";
          for (var i = 0; i < val.length; i++) {
            if (digits.indexOf(val.charAt(i)) == -1) {
              return false;
            }
          }
          return true;
        }

        function _getInt(str, i, minlength, maxlength) {
          for (var x = maxlength; x >= minlength; x--) {
            var token = str.substring(i, i + x);
            if (token.length < minlength) {
              return null;
            }

            if (_isInteger(token)) {
              return token;
            }
          }
          return null;
        }

        function getDateFromFormat(val, format) {
          val = val + "";
          format = format + "";
          var i_val = 0;
          var i_format = 0;
          var c = "";
          var token = "";
          var token2 = "";
          var x,
          y;
          var now = new Date();
          var year = now.getYear();
          var month = now.getMonth() + 1;
          var date = 1;
          var hh = now.getHours();
          var mm = now.getMinutes();
          var ss = now.getSeconds();
          var ampm = "";

          while (i_format < format.length) {
            // Get next token from format string
            c = format.charAt(i_format);
            token = "";
            while ((format.charAt(i_format) == c) && (i_format < format.length)) {
              token += format.charAt(i_format++);
            }

            // Extract contents of value based on format token
            if (token == "yyyy" || token == "yy" || token == "y") {
              if (token == "yyyy") {
                x = 4;
                y = 4;
              }
              if (token == "yy") {
                x = 2;
                y = 2;
              }
              if (token == "y") {
                x = 2;
                y = 4;
              }
              year = _getInt(val, i_val, x, y);
              if (year == null) {
                return 0;
              }
              i_val += year.length;
              if (year.length == 2) {
                if (year > 70) {
                  year = 1900 + (year - 0);
                }
                else {
                  year = 2000 + (year - 0);
                }
              }
            } else if (token == "MMM" || token == "NNN") {
              month = 0;
              for (var i = 0; i < MONTH_NAMES.length; i++) {
                var month_name = MONTH_NAMES[i];
                if (val.substring(i_val, i_val + month_name.length).toLowerCase() == month_name.toLowerCase()) {
                  if (token == "MMM" || (token == "NNN" && i > 11)) {
                    month = i + 1;
                    if (month > 12) {
                      month -= 12;
                    }
                    i_val += month_name.length;
                    break;
                  }
                }
              }

              if ((month < 1) || (month > 12)) {
                return 0;
              }
            }
            else if (token == "EE" || token == "E") {
              for (var i = 0; i < DAY_NAMES.length; i++) {
                var day_name = DAY_NAMES[i];
                if (val.substring(i_val, i_val + day_name.length).toLowerCase() == day_name.toLowerCase()) {
                  i_val += day_name.length;
                  break;
                }
              }
            }
            else if (token == "MM" || token == "M") {
              month = _getInt(val, i_val, token.length, 2);
              if (month == null || (month < 1) || (month > 12)) {
                return 0;
              }
              i_val += month.length;
            } else if (token == "dd" || token == "d") {
              date = _getInt(val, i_val, token.length, 2);
              if (date == null || (date < 1) || (date > 31)) {
                return 0;
              }
              i_val += date.length;
            } else if (token == "hh" || token == "h") {
              hh = _getInt(val, i_val, token.length, 2);
              if (hh == null || (hh < 1) || (hh > 12)) {
                return 0;
              }
              i_val += hh.length;
            } else if (token == "HH" || token == "H") {
              hh = _getInt(val, i_val, token.length, 2);
              if (hh == null || (hh < 0) || (hh > 23)) {
                return 0;
              }
              i_val += hh.length;
            } else if (token == "KK" || token == "K") {
              hh = _getInt(val, i_val, token.length, 2);
              if (hh == null || (hh < 0) || (hh > 11)) {
                return 0;
              }
              i_val += hh.length;
            } else if (token == "kk" || token == "k") {
              hh = _getInt(val, i_val, token.length, 2);
              if (hh == null || (hh < 1) || (hh > 24)) {
                return 0;
              }
              i_val += hh.length;
              hh--;
            }
            else if (token == "mm" || token == "m") {
              mm = _getInt(val, i_val, token.length, 2);
              if (mm == null || (mm < 0) || (mm > 59)) {
                return 0;
              }
              i_val += mm.length;
            } else if (token == "ss" || token == "s") {
              ss = _getInt(val, i_val, token.length, 2);
              if (ss == null || (ss < 0) || (ss > 59)) {
                return 0;
              }
              i_val += ss.length;
            } else if (token == "a") {
              if (val.substring(i_val, i_val + 2).toLowerCase() == "am") {
                ampm = "AM";
              }
              else if (val.substring(i_val, i_val + 2).toLowerCase() == "pm") {
                ampm = "PM";
              }
              else {
                return 0;
              }
              i_val += 2;
            } else {
              if (val.substring(i_val, i_val + token.length) != token) {
                return 0;
              }
              else {
                i_val += token.length;
              }
            }
          }
          // If there are any trailing characters left in the value, it doesn't match
          if (i_val != val.length) {
            return 0;
          }
          // Is date valid for month?
          if (month == 2) {
            // Check for leap year
            if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
              // leap year
              if (date > 29) {
                return 0;
              }
            } else {
              if (date > 28) {
                return 0;
              }
            }
          }
          if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
            if (date > 30) {
              return 0;
            }
          }
          // Correct hours value
          if (hh < 12 && ampm == "PM") {
            hh = hh - 0 + 12;
          }
          else if (hh > 11 && ampm == "AM") {
            hh -= 12;
          }
          var newdate = new Date(year, month - 1, date, hh, mm, ss);
          return newdate.getTime();
        }

        function parseDate(val) {
          var preferEuro = (arguments.length == 2) ? arguments[1] : false;
          generalFormats = new Array('y-M-d', 'MMM d, y', 'MMM d,y', 'y-MMM-d', 'd-MMM-y', 'MMM d');
          monthFirst = new Array('M/d/y', 'M-d-y', 'M.d.y', 'MMM-d', 'M/d', 'M-d');
          dateFirst = new Array('d/M/y', 'd-M-y', 'd.M.y', 'd-MMM', 'd/M', 'd-M');
          var checkList = new Array('generalFormats', preferEuro ? 'dateFirst': 'monthFirst', preferEuro ? 'monthFirst': 'dateFirst');
          var d = null;
          for (var i = 0; i < checkList.length; i++) {
            var l = window[checkList[i]];
            for (var j = 0; j < l.length; j++) {
              d = getDateFromFormat(val, l[j]);
              if (d != 0) {
                return new Date(d);
              }
            }
          }
          return null;
        }

      });
    },

    stop: function() {
      return this.each(function() {
        var containerDiv = $(this);
        var ai = containerDiv.data('animateInterval');
        if (ai) {
          clearInterval(ai);
        }

        var at = containerDiv.data('animateTimeout');
        if (at) {
          clearTimeout(at);
        }
      });
    }
  };

  //calls the proper method based on the string passed
  $.fn.snapplefbFanpageWall = function(method) {
    if (methods[method]) {
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof method === 'object' || !method) {
      return methods.init.apply(this, arguments);
    } else {
      $.error('Method ' + method + ' does not exist on snapplefbFanpageWall');
    }
  };

})(jQuery);

