/**
 * @name ActivityFeed
 * @description ActivityFeed is an plugin displaying in a feed with carousel and caching
 * @author Marek Kalnik <marekk@theodo.fr>
 * @since  2011-05-04
 */

(function($)
{
  /**
   * Parameters:
   * - url (required)    ajax source
   * - rotateInterval
   * - updateInterval
   * - tag
   * - page              page to start from
   * - seenIds
   * - limit             limit pages
   * - maxDisplayed      limit displayed nodes
   */
  $.fn.mrActivityFeed = function(params)
  {
    return this.each(function()
    {
      // Default intervals
      params = $.extend(
      {
        'rotateInterval' : 3000,
        'updateInterval': 5000,
        'slideDelay':     1000,
        'tag': 'li',
        'page': 2,
        'maxDisplayed': 6
      }, params);

      var cache = function()
      {
        return{
          _results:   [],
          _displayed: [],

          getResult: function()
          {
            if (this._results.length < 5) {

              if (env.status !== 'stopped') {
                methods.update();
              }

              if (this._results.length === 0) {
                if (this._displayed.length === 0) {
                  return null;
                }

                this._results   = this._displayed.slice(0);
                this._displayed = [];
              }
            }

            var result = this._results.shift();
            this._displayed.push(result);

            return result;
          },

          addResult: function(tag)
          {
            this._results.push(tag);
          },

          addDisplayed: function(tag)
          {
            this._displayed.push(tag);
          }
        };
      };

      var env = {
        'node':    $(this),
        'seenIds': [],
        'cache':   cache(),
        'status':  'running'
      };

      var methods = {

        /**
         * Configure, set the rotation interval,
         * call the first update
         */
        _run: function()
        {
          methods._configure();
          setInterval(methods._rotate, params.rotateInterval);
          methods.update();
        },

        /**
         * Register first displayed news items in the local cache,
         * those initially loaded without ajax
         */
        _configure: function()
        {
          if (typeof params.url === 'undefined' || params.url.length === 0) {
            throw "You need to pass an URL parameter";
          }

          $.extend(env, {
            'page':    params.page,
            'seenIds': params.seenIds
          });

          // We save old nodes
          env.node.children().each(function(key, node) {
            env.cache.addDisplayed($(node));
          });
        },

        /**
         * Rotate news items
         */
        _rotate: function()
        {
          var newsItem = env.cache.getResult();
          if (newsItem === null) {
            return;
          }

          $(env.node).children('li:first').removeClass('first');
          newsItem.addClass('first')
                  .hide()
                  .prependTo(env.node)
                  .slideDown(params.slideDelay);

          if (env.node.children('li').length > params.maxDisplayed) {
            env.node.children('li:last').slideUp(params.slideDelay, function() {
              $(this).remove();
            });
          }
        },

        update: function()
        {
          if ((typeof params.limit === 'number' && env.page >= params.limit) || env.status === 'stopped') {
            env.status = 'stopped';
            return false;
          }

          $.ajax({
            url:      params.url,
            data:     {'page': env.page},
            dataType: 'json',
            success:  function (response) {
              if (response.length === 0) {
                env.status = 'stopped';
              }
              env.page += 1;
              $.each(response, function() {
                if ($.inArray(this.id, env.seenIds) === -1) {
                  var $item = $('<' + params.tag + '>' + this.html + '</' + params.tag + '>');
                  env.cache.addResult($item);
                  env.seenIds.push(this.id);
                }
              });
            }
          });
        }
      };

      methods._run();
    });
  };
})(jQuery);
