/*
 * Copyright (c) 2011 TWIMPACT UG (haftungsbeschraenkt). All rights reserved.
 */

(function($, w) {
  "use strict";

  // ensure we have initialized the namespace for twimpact
  w.Twimpact = w.Twimpact || {};

  var R_REGEXP_LITERAL = /[*+\[\](){}$.?\\^]/;
  var R_URL = /^[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+$/g;
  var R_USER_HASHTAG = /[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+|[@#]\w+/g;

  Twimpact.Formatter = function(options) {
    $.extend(this, options || {});
  };

  $.extend(Twimpact.Formatter.prototype, {
    userLink: '@<a href="http://www.twitter.com/${0}" target="_blank">${1}</a>',
    hashtagLink: '#<a href="http://search.twitter.com/search?q=%23${0}" target="_blank">${1}</a>',
    urlLink: '<a href="${0}" target="_blank">${1}</a>',

    /**
     * Format the text that is found betwen links, hashtags and user mentions.
     * This callback can be used for extra-formatting, coloring etc.
     * @see Twimpact.KeywordFormatter
     * @param text the text to be formatted
     * @return the formatted text
     */
    formatText: function(text) {
      return text;
    },

    /**
     * Format some text that origins as tweet text with links, hashtags and user mentions.
     * @param text the text
     * @return formatted text
     */
    format: function(text) {
      var lastIndex = 0;
      var result = "";
      var formatter = this;
      text.replace(R_USER_HASHTAG, function(match, index) {
        //app.log('match="'+match+'", index="'+index+'", original="'+original+'"');
        if (lastIndex < index) {
          result += formatter.formatText(text.substring(lastIndex, index));
        }
        lastIndex = index + match.length;
        if (match[0] == '@') {
          result += formatter.userLink
              .replace("${0}", encodeURI(match.substring(1)))
              .replace("${1}", formatter.formatText(match.substring(1)));
        } else if (match[0] == '#') {
          result += formatter.hashtagLink
              .replace("${0}", encodeURI(match.substring(1)))
              .replace("${1}", formatter.formatText(match.substring(1)));
        }
        if (R_URL.test(match)) {
          result += formatter.urlLink
              .replace("${0}", match)
              .replace("${1}", formatter.formatText(match));
        }
        return "";
      });
      if (lastIndex < text.length) {
        result += formatter.formatText(text.substring(lastIndex));
      }
      return result;
    }
  });

  Twimpact.KeywordFormatter = function(keywords, options) {
    $.extend(this, options);
    this.setKeywords(keywords)
  };


  $.extend(Twimpact.KeywordFormatter.prototype, Twimpact.Formatter.prototype, {
    setKeywords: function(keywords) {
      delete this.keywordRegexp;
      if (keywords.length) {
        var patterns = [];
        for (var i = 0, l = keywords.length; i < l; i++) {
          patterns.push(keywords[i].replace(R_REGEXP_LITERAL, "\\$1"));
        }
        this.keywordsRegexp = new RegExp("(" + patterns.join("|") + ")", "gi");
      }
    },

    formatKeyword: function(keyword) {
      return keyword;
    },

    formatText: function(text) {
      if (this.keywordsRegexp) {
        var formatter = this;
        text = text.replace(formatter.keywordsRegexp, function(m, k) {
          return formatter.formatKeyword(k);
        });
      }
      return text;
    }
  });

})(jQuery, window);
