/*global jQuery, window, Date */ // for jslint.com

(function ($) {
  var userLink = function (user, content, id) {
    return $('<a />').attr('href', 'http://twitter.com/' + user + (id ? '/statuses/' + id : '')).append(content);
  };

  var span = function (klass, content) {
    return $('<span />').addClass(klass).append(content);
  };

  var meta = function (tweet) {
    var createdAt = new Date(tweet.created_at);
    var meta = span('meta', userLink(tweet.from_user, 'at ' + createdAt.toLocaleTimeString() + ' on ' + createdAt.toLocaleDateString(), tweet.id)).append(' from ' + $('<div>').html(tweet.source).text());

    if (tweet.to_user) {
      meta.append(' ').append(userLink(tweet.to_user, 'in reply to ' + tweet.to_user));
    }

    return meta;
  };

  var urlRegex = /https?:\/\/[\-\w]+(?:\.[\-\w]+)*(?::\d+)?(?:\/(?:[~\w\+@%=\(\)\-]|(?:[,.;:'][^\s$]))*)*(?:\?[\w\+@%&=.;:\-]+)?(?:\#[\w\-]*)?/g;
  var userRegex = /(^|[^\w])@([\w]+)/g;
  var autoLink = function (string) {
    return string.
      replace(urlRegex, '<a href="$&">$&</a>').
      replace(userRegex, '$1<a href="http://twitter.com/$2">@$2</a>');
  };

  var buildTweet = function (tweet) {
    return $('<li />').

    // image
    append(span('author', userLink(tweet.from_user, $('<img />').attr('src', tweet.profile_image_url)))).

    // content
    append(
      span('body').

      // author
      append($('<strong />').append(userLink(tweet.from_user, tweet.from_user))).

      append(' ').

      // text
      append(span('text', autoLink(tweet.text))).

      // meta
      append(meta(tweet))
    );
  };

  $.fn.twitter = function (options) {
    var tweets = this;

    var query = options.query;
    var loadInterval = options.loadInterval;
    var showInterval = options.showInterval;
    var maxTweets = options.maxTweets;

    var loadTweets = function (since) {
      if (!since) {
        since = 0;
      }

      $.getJSON('http://search.twitter.com/search.json?callback=?', { q: query, rpp: maxTweets, since_id: since }, function (json) {
        // stash hidden tweets at the top
        $.each(json.results.reverse(), function () {
          buildTweet(this).hide().prependTo(tweets);
        });

        window.setTimeout(function () { loadTweets(json.max_id); }, loadInterval);
      });
    };

    var showTweet = function () {
      if (tweets.children(':visible').length > 0) {
        // reveal a hidden tweet at the top
        tweets.children(':hidden:last').slideDown();

        // hide any surplus tweets at the bottom
        tweets.children(':visible:gt(' + (maxTweets - 1) + ')').slideUp(function () { $(this).remove(); });
      } else {
        tweets.children().fadeIn();
      }
    };

    $(function () {
      loadTweets();
      window.setInterval(showTweet, showInterval);
    });

    return this;  // return the jQuery object
  };
})(jQuery);
