<commit_before><!DOCTYPE html>
<html>
<head>
<!-- Theme specific CSS files are loaded later by the ThemeManager -->
<link id="base_stylesheet" rel="stylesheet" type="text/css" href="css/base.css" />
<link rel="stylesheet" type="text/css" href="css/simple_select.css" />
<link rel="stylesheet" type="text/css" href="css/tipsy.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.contextMenu.css" />

<script>
var MAX_TWEET_SIZE = 140;
var Persistence = chrome.extension.getBackgroundPage().Persistence;
var urlExpander = chrome.extension.getBackgroundPage().urlExpander;
var tweetManager = chrome.extension.getBackgroundPage().TweetManager.instance;
var twitterBackend = tweetManager.twitterBackend;
var OptionsBackend = chrome.extension.getBackgroundPage().OptionsBackend;
var TimelineTemplate = chrome.extension.getBackgroundPage().TimelineTemplate;

var microbloggingService = OptionsBackend.get('microblogging_service');
var TwitterLib;
if(microbloggingService == 'twitter') {
  TwitterLib = {
    URLS: {
      BASE: 'http://twitter.com/',
      SEARCH: 'http://twitter.com/search?q='
    }
  };
} else if(microbloggingService == 'identica') {
  TwitterLib = {
    URLS: {
      BASE: 'http://identi.ca/',
      SEARCH: 'http://identi.ca/search/notice?q='
    }
  };
}

if(!twitterBackend.authenticated() && !twitterBackend.tokenRequested()) {
  twitterBackend.startAuthentication();
  window.close();
}
</script>

<script type="text/javascript" src="lib/3rdparty/jquery.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery-ui-custom.js"></script>
<script type='text/javascript' src='lib/3rdparty/jquery.tipsy.js'></script>
<script type="text/javascript" src="lib/3rdparty/jquery.contextMenu.js"></script>

<!--script type="text/javascript" src="lib/debug.js"></script-->
<script type="text/javascript" src="lib/shortener_lib.js"></script>
<script type="text/javascript" src="lib/simple_select.js"></script>
<script>

var shortener_acct = OptionsBackend.get('shortener_acct');
var shortener_login = null;
var shortener_key = null;
if(shortener_acct) {
  shortener_login = OptionsBackend.get('shortener_login');
  shortener_key = OptionsBackend.get('shortener_key');
}
var reply_all = OptionsBackend.get('reply_all');
var shortener = new Shortener(OptionsBackend.get('url_shortener'),
  shortener_acct, shortener_login, shortener_key);

$.extend($.ui.tabs.prototype, {
  refreshPositions: function() {
    return this._tabify();
  }
});

$.fn.hoverFor = function(time, mainCallback, startingCallback, abortCallback) {
  return this.each(function(){
    var _this = this, timeoutHandle, triggerFired = false;
    $(this).hover(
      function() {
        if(triggerFired)
          return;
        if(startingCallback)
          startingCallback.call(_this);
        timeoutHandle = setTimeout(function() {
          triggerFired = true;
          mainCallback.call(_this);
          timeoutHandle = null;
        }, time);
      },
      function() {
        if(triggerFired)
          return;
        if(timeoutHandle) {
          if(abortCallback)
            abortCallback.call(_this);
          clearTimeout(timeoutHandle);
          timeoutHandle = null;
        }
      }
    );
 });
};

var OAuth = {
  registerPin: function() {
    var pinNumber = $("input[name='pin']").val();
    $("#loading_oauth").show();
    twitterBackend.oauthLib.getAccessToken(pinNumber, function(result) {
      $("#loading_oauth").hide();
      $("#enter_pin").hide();
      if(result) {
        initializeWorkspace();
      } else {
        var errMsg = twitterBackend.oauthLib.error;
        $("#error_pin").show().html('The following error occurred trying to authenticate: ' + errMsg + '. ' +
          'Please, <a href="javascript:OAuth.requestNewToken();">click here to restart the authentication process</a>');
      }
    });
  },
  requestNewToken: function() {
    twitterBackend.startAuthentication();
    window.close();
  }
};

var Paginator = {
  needsMore: false,
  firstPage: function(shouldScrollTop) {
    this.needsMore = false;
    if(shouldScrollTop) {
      $("#timeline-" + tweetManager.currentTimelineId + ' .inner_timeline').scrollTop(0);
    }
  },
  nextPage: function() {
    this.needsMore = true;
    loadTimeline();
  }
}

var ThemeManager = {
  init: function () {
    $("link.theme").remove();
    var theme = OptionsBackend.get('theme');
    $(theme.split(",")).each(function(i, p) {
      $("<link rel='stylesheet' type='text/css' class='theme' href='" + p + "'>").appendTo(document.head);
    });
    var baseStyle = $("#base_stylesheet")[0];
    if(baseStyle.sheet && baseStyle.sheet.cssRules) {
      var baseRules = baseStyle.sheet.cssRules;
      var fontFamily = OptionsBackend.get('font_family');
      var fontSize = OptionsBackend.get('font_size');
      for(var i = 0, len = baseRules.length; i < len; ++i) {
        var rule = baseRules[i];
        if(rule.selectorText == ".tweet") {
          rule.style.fontFamily = fontFamily;
          rule.style.fontSize = fontSize;
          break;
        }
      }
    }
  },
  setPopupSize: function(width, height, autoFitWidth) {
    width = width || 490;
    if(autoFitWidth) {
      setTimeout(function() {
        var tabsBarWidth = 0;
        $("li.timeline_tab").each(function() {
          tabsBarWidth += $(this).width();
        });
        tabsBarWidth += 40;
        if(tabsBarWidth > width) {
          ThemeManager.setPopupSize(tabsBarWidth, height);
        }
      }, 300);
    }
    $(".timeline").width(width + 'px');
    if(height) {
      $(".inner_timeline,.timeline").height(height + 'px');
    } else {
      $(".inner_timeline,.timeline").height('400px');
    }
  },
  popupSizeData: Persistence.popupSize(),
  handleWindowResizing: function () {
    var sizeArray = ThemeManager.popupSizeData.val();
    if(sizeArray) {
      sizeArray = sizeArray.split('x');
      ThemeManager.setPopupSize(sizeArray[0], sizeArray[1], true);
    } else {
      ThemeManager.setPopupSize(null, null, true);
    }
    $(".timeline").resizable({
      handles: 'e, s, se',
      minWidth: 450,
      resize: function(e, ui) {
        var $this = $(this);
        ThemeManager.setPopupSize($this.width(), $this.height());
      },
      stop: function(e, ui) {
        var $this = $(this);
        ThemeManager.popupSizeData.save($this.width() + 'x' + $this.height());
      }
    });
    $(".ui-resizable-handle").attr('title', 'Double click to reset size');
    $(".ui-resizable-handle").dblclick(function(e) {
      ThemeManager.popupSizeData.remove();
      ThemeManager.setPopupSize(null, null, true);
    });
  },

  sortableEl: null,
  uiTabs: null,
  handleSortableTabs: function() {
    this.uiTabs = $("#tabs");
    this.sortableEl = this.uiTabs.find(".ui-tabs-nav");
    this.sortableEl.sortable({
      stop: function(event, ui) {
        ThemeManager.updateTabsOrder();
      }
    });
  },

  reOrderPanels: function(sortedTimelines) {
    var panels = $("#tabs .ui-tabs-panel");
    for(var i = 0, len = sortedTimelines.length; i < len; ++i) {
      var correctTimeline = sortedTimelines[i];
      var correctPanel = $("#timeline-" + correctTimeline);
      var positionPanel = panels.eq(i);
      if(correctPanel[0].id != positionPanel[0].id) {
        correctPanel.remove();
        positionPanel.before(correctPanel);
        panels = $("#tabs .ui-tabs-panel");
      }
    }
  },

  updateTabsOrder: function() {
    var sortedTabs = this.sortableEl.sortable('toArray');
    var sortedTimelines = [];
    for(var i = 0; i < sortedTabs.length; ++i) {
      sortedTimelines[i] = sortedTabs[i].split('-')[1];
    }
    tweetManager.setTimelineOrder(sortedTimelines);
    this.reOrderPanels(sortedTimelines);
    this.uiTabs.tabs('refreshPositions');
  }
}

var Composer = {
  replyId: null,
  replyUser: null,
  rtId: null,
  destroyId: null,
  favoriteId: null,
  destroyTimelineId: null,

  init: function() {
    if(tweetManager.composerData.isComposing) {
      Composer.replyId = tweetManager.composerData.replyId;
      Composer.replyUser = tweetManager.composerData.replyUser;
      $("#compose_tweet_area textarea").val(tweetManager.composerData.saveMessage || '');
      Composer.showComposeArea(true, true);
    }
    Composer.textareaChanged();
  },

  share: function (node) {
    Composer.showComposeArea(true);
    var el = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var msg = $(".text", node).text();
    el.val("RT @" + user + ": " + msg);
    Composer.textareaChanged();
  },

  confirmDestroy: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;

    tweetManager.destroy(function(success, data, status) {
      $("#loading").hide();
      var notFound = status && status.match(/Not Found/);
      if(success || notFound) {
        $(".tweet[tweetid='" + _this.destroyId + "']").hide('blind', { direction: "vertical" });
        var currentCount = tweetManager.getCurrentTimeline().getTweetsCache().length;
        if(currentCount < OptionsBackend.get('tweets_per_page')) {
          Paginator.nextPage();
        }
      } else {
        Renderer.showError('Unexpected error ' + status + ' deleting tweet.', 'Composer.confirmDestroy');
      }
    }, this.destroyTimelineId, this.destroyId);
  },

  denyDestroy: function() {
    $(".rt_confirm").hide();
  },

  destroy: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm.destroy", node).show();
    this.destroyId = $(node).attr('tweetid');
    this.destroyTimelineId = $(node).attr('timelineid');
  },

  confirmRT: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;
    tweetManager.postRetweet(function(success, data, status) {
      $("#loading").hide();
      if(success) {
        loadTimeline(true, "home");
      } else {
        Renderer.showError('Unexpected error ' + status + ' retweeting.', 'Composer.confirmRT');
      }
    }, _this.rtId);
  },

  denyRT: function() {
    $(".rt_confirm").hide();
  },

  retweet: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm", node).show();
    this.rtId = $(node).attr('tweetid');
  },

  favorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.favorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError('Unexpected error ' + status + ' marking as favorite.', 'Composer.favorite');
      }
    }, this.favoriteId);
  },

  unFavorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.unFavorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError('Unexpected error ' + status + ' unmarking as favorite.', 'Composer.unFavorite');
      }
    }, this.favoriteId);
  },

  addUser: function (user, replies) {
    var textArea = $("#compose_tweet_area textarea");
    var currentVal = textArea.val();
    var replies =  replies || [];
    if(currentVal.length > 0 && currentVal[currentVal.length - 1] != ' ') {
      currentVal += ' ';
    }
    currentVal += '@' + user + ' ' + replies.join('');
    textArea.val(currentVal);
  },

  reply: function (node) {
    Composer.showComposeArea(true);

    var textArea = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var timelineId = $(node).attr('timelineid');

    if(timelineId == "dms") {
      textArea.val("d " + user + " ");
      Composer.textareaChanged();
      return;
    }

    var currentVal = textArea.val();
    var replies = [];
    var ownName = tweetManager.twitterBackend.username();
    if (reply_all) {
      $(".text a", node).each(function(){
        var t = $(this).text();
        if (t !== ownName && /^[A-Z0-9_-]{1,15}$/i.test(t)) {
          replies.push('@'+t+' ');
        }
      });
    }

    if(Composer.replyId && currentVal.indexOf(Composer.replyUser) != -1) {
      this.addUser(user, replies);
      Composer.textareaChanged();
      return;
    }

    this.addUser(user, replies);
    tweetManager.composerData.replyId = Composer.replyId = $(node).attr('tweetid');
    tweetManager.composerData.replyUser = Composer.replyUser = user;

    Composer.textareaChanged();
  },

  showComposeArea: function (showOnly, noAnimation) {
    var composeArea = $("#compose_tweet_area");
    var textarea = $("textarea", composeArea);
    var visible = composeArea.is(':visible');

    if(!visible) {
      if(noAnimation) {
        composeArea.show();
      } else {
        composeArea.show('blind', { direction: "vertical" }, 'normal', function() {
          textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
          textarea.focus();
        });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_up.gif');
      tweetManager.composerData.isComposing = true;
      tweetManager.composerData.replyId = Composer.replyId;
      tweetManager.composerData.replyUser = Composer.replyUser;
    } else if(!showOnly) {
      if(noAnimation) {
        composeArea.hide();
      } else {
        composeArea.hide('blind', { direction: "vertical" });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_down.gif');
      tweetManager.composerData.saveMessage = '';
      tweetManager.composerData.isComposing = false;
      tweetManager.composerData.replyId = null;
      tweetManager.composerData.replyUser = null;
      Shortener.closeArea();
    }

    if((visible && showOnly) || (!visible && noAnimation)) {
      textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
      textarea.focus();
    }
  },

  textareaChanged: function (e) {
    var el = $("#compose_tweet_area textarea");
    tweetManager.composerData.saveMessage = el.val();
    var availableChars = MAX_TWEET_SIZE - el.val().length;
    var charsLeftEl = $("#compose_tweet_area .chars_left");
    charsLeftEl.text(availableChars);
    if(availableChars < 0 || availableChars == MAX_TWEET_SIZE) {
      if(availableChars < 0) {
        charsLeftEl.css('color', 'red');
      }
      $("#compose_tweet_area input[type='button']").attr("disabled", "disabled");
    } else {
      charsLeftEl.css('color', 'black');
      $("#compose_tweet_area input[type='button']").removeAttr("disabled");
      if(e && e.ctrlKey && e.which == 13) { // Ctrl + Enter
        this.sendTweet();
      }
    }
  },

  sendTweet: function () {
    $("#loading").show();
    $("#compose_tweet_area input[type='button']").attr("disabled", "disabled");
    $("#compose_tweet_area textarea").attr("disabled", "disabled");
    tweetManager.postTweet(function(success, data, status) {
      $("#loading").hide();
      $("#compose_tweet_area input[type='button']").removeAttr("disabled");
      $("#compose_tweet_area textarea").removeAttr("disabled");
      if(success) {
        var textArea = $("#compose_tweet_area textarea");
        var msg = textArea.val();
        Composer.replyId = null;
        Composer.textareaChanged();
        Composer.showComposeArea();
        Shortener.clear();

        if(!msg.match(/^d\s\w*?\s/i)) {
          loadTimeline(true, "home");
        }
        textArea.val("");
      } else {
        $("#compose_tweet_area textarea").focus();
        Renderer.showError('Unexpected error ' + status + ' sending tweet.', 'Composer.sendTweet');
      }
    }, $("#compose_tweet_area textarea").val(), Composer.replyId);
  },

  refreshNew: function() {
    if($("#loading").is(":visible")) {
      return;
    }
    loadTimeline(true);
  }
}

var Shortener = {
  SHORTENER_IDLE_STR: 'Type a URL to make it shorter, or, click right here \u2192',

  init: function() {
    var savedUrl = tweetManager.composerData.urlShortener;
    if(savedUrl != '') {
      $("#shortener_area input").val(savedUrl);
    }
    this.blur();
  },

  clear: function() {
    $("#shortener_area input").val('');
    this.blur();
  },

  closeArea: function() {
    tweetManager.composerData.urlShortener = '';
  },

  focus: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if(val == this.SHORTENER_IDLE_STR) {
      shortener.val('');
      shortener.removeAttr('style');
    }
  },

  showButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(!shortenerButton.is(":visible"))
      shortenerButton.show('blind', { direction: "vertical" }, 'fast');
  },

  hideButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(shortenerButton.is(":visible"))
      shortenerButton.hide('blind', { direction: "vertical" }, 'fast');
  },

  blur: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if($.trim(val) == '' || val == this.SHORTENER_IDLE_STR) {
      shortener.val(this.SHORTENER_IDLE_STR);
      shortener.attr('style', 'color: #aaa;');
      this.hideButton();
    } else {
      this.showButton();
    }
  },

  changed: function(e) {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    tweetManager.composerData.urlShortener = val;
    if($.trim(val) != '') {
      if(e.which == 13) { //Enter key
        this.shortenIt();
      } else {
        this.showButton();
      }
    } else {
      this.hideButton();
    }
  },

  shortenCurrentPage: function() {
    var _this = this;
    chrome.tabs.getSelected(null, function(tab) {
      var shortenerInput = $("#shortener_area input");
      shortenerInput.val(tab.url);
      _this.shortenIt({title: tab.title});
    });
  },

  shortenIt: function(context) {
    var shortenerInput = $("#shortener_area input");
    var longUrl = shortenerInput.val();
    this.shortenPage(longUrl, context);
  },

  shortenPage: function(longUrl, context) {
    $("#loading").show();
    var shortenerInput = $("#shortener_area input");
    shortenerInput.attr('disabled', 'disabled');
    this.hideButton();
    var _this = this;
    shortener.shorten(longUrl, function(success, shortUrl) {
      $("#loading").hide();
      shortenerInput.removeAttr('disabled');
      _this.closeArea();
      _this.clear();
      var textarea = $("#compose_tweet_area textarea");
      if(success && shortUrl) {
        var newText = textarea.val();
        if(newText.length > 0 && newText[newText.length - 1] != ' ') {
          newText += ' ';
        }
        if(context && context.title && OptionsBackend.get('share_include_title')) {
          shortUrl = context.title + ' - ' + shortUrl;
        }
        newText += shortUrl;
        textarea.val(newText);
        Composer.textareaChanged();
      } else if(!success) {
        Renderer.showError(shortUrl);
      }
      Composer.showComposeArea(true);
    });
  }
}

var Renderer = {
  getTimestampText: function (inputTimestampStr) {
    var inputTimestamp = Date.parse(inputTimestampStr);
    var nowTimestamp = new Date().getTime();

    var diff = (nowTimestamp - inputTimestamp) / 1000;
    if(diff < 15) {
      return "just now";
    } else if(diff < 60) {
      return "less than 1 minute ago";
    } else if(diff < 60 * 60) {
      var minutes = parseInt(diff / 60);
      return minutes + " minute" + ((minutes > 1) ? "s" : "") + " ago";
    } else if(diff < 60 * 60 * 24) {
      var hours = parseInt(diff / (60 * 60));
      return "about " + hours + " hour" + ((hours > 1) ? "s" : "") + " ago";
    } else if(diff < 60 * 60 * 24 * 30) {
      var days = parseInt(diff / (60 * 60 * 24));
      return "about " + days + " day" + ((days > 1) ? "s" : "") + " ago";
    } else if(diff < 60 * 60 * 24 * 30 * 12) {
      var months = parseInt(diff / (60 * 60 * 24 * 30));
      return "about " + months + " month" + ((months > 1) ? "s" : "") + " ago";
    } else {
      return "years ago";
    }
  },

  getTimestampAltText: function (inputTimestampStr) {
    var inputTimestamp = Date.parse(inputTimestampStr);
    return new Date(inputTimestamp).toLocaleDateString() + " " + new Date(inputTimestamp).toLocaleTimeString();
  },

  geoImage: function (aElement, lat, long, name) {
    var lat = lat.toFixed(6).toString().replace(".", "");
    var long = long.toFixed(6).toString().replace(".", "");
    var url = 'http://maps.google.com/mapdata?cc=JP&min_priority=1&w=160&h=160&latitude_e6=' + lat + '&longitude_e6=' + long + '&zm=2000&Point=b&Point.latitude_e6=' + lat + '&Point.longitude_e6=' + long + '&Point.iconid=33&Point=e';
    $(aElement).tipsy({
      title: function() {
        return '<img src="img/loading.gif" /> Loading map...';
      },
      image: url,
      html: true,
      showNow: true,
      opacity: 1.0,
      gravity: $.fn.tipsy.autoWE
    });
  },

  expandLink: function (aElement, url) {
    if(!OptionsBackend.get('show_expanded_urls')) {
      return;
    }
    var m = url.match(/http:\/\/(www\.)?(twitpic|twitgoo|yfrog|movapic).com\/(.*)/);
    if(m) {
      var srcUrl = null;
      if(m[2] == "twitpic" || m[2] == "twitgoo") {
        srcUrl = "http://" + m[2] + ".com/show/thumb/" + m[3];
      } else if(m[2] == "yfrog") {
        srcUrl = "http://yfrog.com/" + m[3] + ".th.jpg";
      } else if(m[2] == "movapic") {
        var iid = m[3].split(/\//)[1];
        srcUrl = "http://image.movapic.com/pic/t_" + iid + ".jpeg";
      }
      if(!srcUrl) {
        return;
      }
      $(aElement).tipsy({<commit_msg>Changing map image URL to use EN country code<commit_after><!DOCTYPE html>
<html>
<head>
<!-- Theme specific CSS files are loaded later by the ThemeManager -->
<link id="base_stylesheet" rel="stylesheet" type="text/css" href="css/base.css" />
<link rel="stylesheet" type="text/css" href="css/simple_select.css" />
<link rel="stylesheet" type="text/css" href="css/tipsy.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.contextMenu.css" />

<script>
var MAX_TWEET_SIZE = 140;
var Persistence = chrome.extension.getBackgroundPage().Persistence;
var urlExpander = chrome.extension.getBackgroundPage().urlExpander;
var tweetManager = chrome.extension.getBackgroundPage().TweetManager.instance;
var twitterBackend = tweetManager.twitterBackend;
var OptionsBackend = chrome.extension.getBackgroundPage().OptionsBackend;
var TimelineTemplate = chrome.extension.getBackgroundPage().TimelineTemplate;

var microbloggingService = OptionsBackend.get('microblogging_service');
var TwitterLib;
if(microbloggingService == 'twitter') {
  TwitterLib = {
    URLS: {
      BASE: 'http://twitter.com/',
      SEARCH: 'http://twitter.com/search?q='
    }
  };
} else if(microbloggingService == 'identica') {
  TwitterLib = {
    URLS: {
      BASE: 'http://identi.ca/',
      SEARCH: 'http://identi.ca/search/notice?q='
    }
  };
}

if(!twitterBackend.authenticated() && !twitterBackend.tokenRequested()) {
  twitterBackend.startAuthentication();
  window.close();
}
</script>

<script type="text/javascript" src="lib/3rdparty/jquery.js"></script>
<script type="text/javascript" src="lib/3rdparty/jquery-ui-custom.js"></script>
<script type='text/javascript' src='lib/3rdparty/jquery.tipsy.js'></script>
<script type="text/javascript" src="lib/3rdparty/jquery.contextMenu.js"></script>

<!--script type="text/javascript" src="lib/debug.js"></script-->
<script type="text/javascript" src="lib/shortener_lib.js"></script>
<script type="text/javascript" src="lib/simple_select.js"></script>
<script>

var shortener_acct = OptionsBackend.get('shortener_acct');
var shortener_login = null;
var shortener_key = null;
if(shortener_acct) {
  shortener_login = OptionsBackend.get('shortener_login');
  shortener_key = OptionsBackend.get('shortener_key');
}
var reply_all = OptionsBackend.get('reply_all');
var shortener = new Shortener(OptionsBackend.get('url_shortener'),
  shortener_acct, shortener_login, shortener_key);

$.extend($.ui.tabs.prototype, {
  refreshPositions: function() {
    return this._tabify();
  }
});

$.fn.hoverFor = function(time, mainCallback, startingCallback, abortCallback) {
  return this.each(function(){
    var _this = this, timeoutHandle, triggerFired = false;
    $(this).hover(
      function() {
        if(triggerFired)
          return;
        if(startingCallback)
          startingCallback.call(_this);
        timeoutHandle = setTimeout(function() {
          triggerFired = true;
          mainCallback.call(_this);
          timeoutHandle = null;
        }, time);
      },
      function() {
        if(triggerFired)
          return;
        if(timeoutHandle) {
          if(abortCallback)
            abortCallback.call(_this);
          clearTimeout(timeoutHandle);
          timeoutHandle = null;
        }
      }
    );
 });
};

var OAuth = {
  registerPin: function() {
    var pinNumber = $("input[name='pin']").val();
    $("#loading_oauth").show();
    twitterBackend.oauthLib.getAccessToken(pinNumber, function(result) {
      $("#loading_oauth").hide();
      $("#enter_pin").hide();
      if(result) {
        initializeWorkspace();
      } else {
        var errMsg = twitterBackend.oauthLib.error;
        $("#error_pin").show().html('The following error occurred trying to authenticate: ' + errMsg + '. ' +
          'Please, <a href="javascript:OAuth.requestNewToken();">click here to restart the authentication process</a>');
      }
    });
  },
  requestNewToken: function() {
    twitterBackend.startAuthentication();
    window.close();
  }
};

var Paginator = {
  needsMore: false,
  firstPage: function(shouldScrollTop) {
    this.needsMore = false;
    if(shouldScrollTop) {
      $("#timeline-" + tweetManager.currentTimelineId + ' .inner_timeline').scrollTop(0);
    }
  },
  nextPage: function() {
    this.needsMore = true;
    loadTimeline();
  }
}

var ThemeManager = {
  init: function () {
    $("link.theme").remove();
    var theme = OptionsBackend.get('theme');
    $(theme.split(",")).each(function(i, p) {
      $("<link rel='stylesheet' type='text/css' class='theme' href='" + p + "'>").appendTo(document.head);
    });
    var baseStyle = $("#base_stylesheet")[0];
    if(baseStyle.sheet && baseStyle.sheet.cssRules) {
      var baseRules = baseStyle.sheet.cssRules;
      var fontFamily = OptionsBackend.get('font_family');
      var fontSize = OptionsBackend.get('font_size');
      for(var i = 0, len = baseRules.length; i < len; ++i) {
        var rule = baseRules[i];
        if(rule.selectorText == ".tweet") {
          rule.style.fontFamily = fontFamily;
          rule.style.fontSize = fontSize;
          break;
        }
      }
    }
  },
  setPopupSize: function(width, height, autoFitWidth) {
    width = width || 490;
    if(autoFitWidth) {
      setTimeout(function() {
        var tabsBarWidth = 0;
        $("li.timeline_tab").each(function() {
          tabsBarWidth += $(this).width();
        });
        tabsBarWidth += 40;
        if(tabsBarWidth > width) {
          ThemeManager.setPopupSize(tabsBarWidth, height);
        }
      }, 300);
    }
    $(".timeline").width(width + 'px');
    if(height) {
      $(".inner_timeline,.timeline").height(height + 'px');
    } else {
      $(".inner_timeline,.timeline").height('400px');
    }
  },
  popupSizeData: Persistence.popupSize(),
  handleWindowResizing: function () {
    var sizeArray = ThemeManager.popupSizeData.val();
    if(sizeArray) {
      sizeArray = sizeArray.split('x');
      ThemeManager.setPopupSize(sizeArray[0], sizeArray[1], true);
    } else {
      ThemeManager.setPopupSize(null, null, true);
    }
    $(".timeline").resizable({
      handles: 'e, s, se',
      minWidth: 450,
      resize: function(e, ui) {
        var $this = $(this);
        ThemeManager.setPopupSize($this.width(), $this.height());
      },
      stop: function(e, ui) {
        var $this = $(this);
        ThemeManager.popupSizeData.save($this.width() + 'x' + $this.height());
      }
    });
    $(".ui-resizable-handle").attr('title', 'Double click to reset size');
    $(".ui-resizable-handle").dblclick(function(e) {
      ThemeManager.popupSizeData.remove();
      ThemeManager.setPopupSize(null, null, true);
    });
  },

  sortableEl: null,
  uiTabs: null,
  handleSortableTabs: function() {
    this.uiTabs = $("#tabs");
    this.sortableEl = this.uiTabs.find(".ui-tabs-nav");
    this.sortableEl.sortable({
      stop: function(event, ui) {
        ThemeManager.updateTabsOrder();
      }
    });
  },

  reOrderPanels: function(sortedTimelines) {
    var panels = $("#tabs .ui-tabs-panel");
    for(var i = 0, len = sortedTimelines.length; i < len; ++i) {
      var correctTimeline = sortedTimelines[i];
      var correctPanel = $("#timeline-" + correctTimeline);
      var positionPanel = panels.eq(i);
      if(correctPanel[0].id != positionPanel[0].id) {
        correctPanel.remove();
        positionPanel.before(correctPanel);
        panels = $("#tabs .ui-tabs-panel");
      }
    }
  },

  updateTabsOrder: function() {
    var sortedTabs = this.sortableEl.sortable('toArray');
    var sortedTimelines = [];
    for(var i = 0; i < sortedTabs.length; ++i) {
      sortedTimelines[i] = sortedTabs[i].split('-')[1];
    }
    tweetManager.setTimelineOrder(sortedTimelines);
    this.reOrderPanels(sortedTimelines);
    this.uiTabs.tabs('refreshPositions');
  }
}

var Composer = {
  replyId: null,
  replyUser: null,
  rtId: null,
  destroyId: null,
  favoriteId: null,
  destroyTimelineId: null,

  init: function() {
    if(tweetManager.composerData.isComposing) {
      Composer.replyId = tweetManager.composerData.replyId;
      Composer.replyUser = tweetManager.composerData.replyUser;
      $("#compose_tweet_area textarea").val(tweetManager.composerData.saveMessage || '');
      Composer.showComposeArea(true, true);
    }
    Composer.textareaChanged();
  },

  share: function (node) {
    Composer.showComposeArea(true);
    var el = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var msg = $(".text", node).text();
    el.val("RT @" + user + ": " + msg);
    Composer.textareaChanged();
  },

  confirmDestroy: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;

    tweetManager.destroy(function(success, data, status) {
      $("#loading").hide();
      var notFound = status && status.match(/Not Found/);
      if(success || notFound) {
        $(".tweet[tweetid='" + _this.destroyId + "']").hide('blind', { direction: "vertical" });
        var currentCount = tweetManager.getCurrentTimeline().getTweetsCache().length;
        if(currentCount < OptionsBackend.get('tweets_per_page')) {
          Paginator.nextPage();
        }
      } else {
        Renderer.showError('Unexpected error ' + status + ' deleting tweet.', 'Composer.confirmDestroy');
      }
    }, this.destroyTimelineId, this.destroyId);
  },

  denyDestroy: function() {
    $(".rt_confirm").hide();
  },

  destroy: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm.destroy", node).show();
    this.destroyId = $(node).attr('tweetid');
    this.destroyTimelineId = $(node).attr('timelineid');
  },

  confirmRT: function() {
    $("#loading").show();
    $(".rt_confirm").hide();
    var _this = this;
    tweetManager.postRetweet(function(success, data, status) {
      $("#loading").hide();
      if(success) {
        loadTimeline(true, "home");
      } else {
        Renderer.showError('Unexpected error ' + status + ' retweeting.', 'Composer.confirmRT');
      }
    }, _this.rtId);
  },

  denyRT: function() {
    $(".rt_confirm").hide();
  },

  retweet: function (node) {
    $(".rt_confirm").hide();
    $(".rt_confirm", node).show();
    this.rtId = $(node).attr('tweetid');
  },

  favorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.favorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError('Unexpected error ' + status + ' marking as favorite.', 'Composer.favorite');
      }
    }, this.favoriteId);
  },

  unFavorite: function (node) {
    if(node) {
      this.favoriteId = $(node).attr('tweetid');
    }
    $("#loading").show();
    tweetManager.unFavorite(function(success, data, status) {
      $("#loading").hide();
      if(success) {
         Paginator.needsMore = false;
         loadTimeline();
      } else {
        Renderer.showError('Unexpected error ' + status + ' unmarking as favorite.', 'Composer.unFavorite');
      }
    }, this.favoriteId);
  },

  addUser: function (user, replies) {
    var textArea = $("#compose_tweet_area textarea");
    var currentVal = textArea.val();
    var replies =  replies || [];
    if(currentVal.length > 0 && currentVal[currentVal.length - 1] != ' ') {
      currentVal += ' ';
    }
    currentVal += '@' + user + ' ' + replies.join('');
    textArea.val(currentVal);
  },

  reply: function (node) {
    Composer.showComposeArea(true);

    var textArea = $("#compose_tweet_area textarea");
    var user = $(".user", node).attr('screen_name');
    var timelineId = $(node).attr('timelineid');

    if(timelineId == "dms") {
      textArea.val("d " + user + " ");
      Composer.textareaChanged();
      return;
    }

    var currentVal = textArea.val();
    var replies = [];
    var ownName = tweetManager.twitterBackend.username();
    if (reply_all) {
      $(".text a", node).each(function(){
        var t = $(this).text();
        if (t !== ownName && /^[A-Z0-9_-]{1,15}$/i.test(t)) {
          replies.push('@'+t+' ');
        }
      });
    }

    if(Composer.replyId && currentVal.indexOf(Composer.replyUser) != -1) {
      this.addUser(user, replies);
      Composer.textareaChanged();
      return;
    }

    this.addUser(user, replies);
    tweetManager.composerData.replyId = Composer.replyId = $(node).attr('tweetid');
    tweetManager.composerData.replyUser = Composer.replyUser = user;

    Composer.textareaChanged();
  },

  showComposeArea: function (showOnly, noAnimation) {
    var composeArea = $("#compose_tweet_area");
    var textarea = $("textarea", composeArea);
    var visible = composeArea.is(':visible');

    if(!visible) {
      if(noAnimation) {
        composeArea.show();
      } else {
        composeArea.show('blind', { direction: "vertical" }, 'normal', function() {
          textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
          textarea.focus();
        });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_up.gif');
      tweetManager.composerData.isComposing = true;
      tweetManager.composerData.replyId = Composer.replyId;
      tweetManager.composerData.replyUser = Composer.replyUser;
    } else if(!showOnly) {
      if(noAnimation) {
        composeArea.hide();
      } else {
        composeArea.hide('blind', { direction: "vertical" });
      }
      $("#compose_tweet img").attr('src', 'img/arrow_down.gif');
      tweetManager.composerData.saveMessage = '';
      tweetManager.composerData.isComposing = false;
      tweetManager.composerData.replyId = null;
      tweetManager.composerData.replyUser = null;
      Shortener.closeArea();
    }

    if((visible && showOnly) || (!visible && noAnimation)) {
      textarea[0].selectionStart = textarea[0].selectionEnd = textarea.val().length;
      textarea.focus();
    }
  },

  textareaChanged: function (e) {
    var el = $("#compose_tweet_area textarea");
    tweetManager.composerData.saveMessage = el.val();
    var availableChars = MAX_TWEET_SIZE - el.val().length;
    var charsLeftEl = $("#compose_tweet_area .chars_left");
    charsLeftEl.text(availableChars);
    if(availableChars < 0 || availableChars == MAX_TWEET_SIZE) {
      if(availableChars < 0) {
        charsLeftEl.css('color', 'red');
      }
      $("#compose_tweet_area input[type='button']").attr("disabled", "disabled");
    } else {
      charsLeftEl.css('color', 'black');
      $("#compose_tweet_area input[type='button']").removeAttr("disabled");
      if(e && e.ctrlKey && e.which == 13) { // Ctrl + Enter
        this.sendTweet();
      }
    }
  },

  sendTweet: function () {
    $("#loading").show();
    $("#compose_tweet_area input[type='button']").attr("disabled", "disabled");
    $("#compose_tweet_area textarea").attr("disabled", "disabled");
    tweetManager.postTweet(function(success, data, status) {
      $("#loading").hide();
      $("#compose_tweet_area input[type='button']").removeAttr("disabled");
      $("#compose_tweet_area textarea").removeAttr("disabled");
      if(success) {
        var textArea = $("#compose_tweet_area textarea");
        var msg = textArea.val();
        Composer.replyId = null;
        Composer.textareaChanged();
        Composer.showComposeArea();
        Shortener.clear();

        if(!msg.match(/^d\s\w*?\s/i)) {
          loadTimeline(true, "home");
        }
        textArea.val("");
      } else {
        $("#compose_tweet_area textarea").focus();
        Renderer.showError('Unexpected error ' + status + ' sending tweet.', 'Composer.sendTweet');
      }
    }, $("#compose_tweet_area textarea").val(), Composer.replyId);
  },

  refreshNew: function() {
    if($("#loading").is(":visible")) {
      return;
    }
    loadTimeline(true);
  }
}

var Shortener = {
  SHORTENER_IDLE_STR: 'Type a URL to make it shorter, or, click right here \u2192',

  init: function() {
    var savedUrl = tweetManager.composerData.urlShortener;
    if(savedUrl != '') {
      $("#shortener_area input").val(savedUrl);
    }
    this.blur();
  },

  clear: function() {
    $("#shortener_area input").val('');
    this.blur();
  },

  closeArea: function() {
    tweetManager.composerData.urlShortener = '';
  },

  focus: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if(val == this.SHORTENER_IDLE_STR) {
      shortener.val('');
      shortener.removeAttr('style');
    }
  },

  showButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(!shortenerButton.is(":visible"))
      shortenerButton.show('blind', { direction: "vertical" }, 'fast');
  },

  hideButton: function() {
    var shortenerButton = $("#shortener_button div");
    if(shortenerButton.is(":visible"))
      shortenerButton.hide('blind', { direction: "vertical" }, 'fast');
  },

  blur: function() {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    if($.trim(val) == '' || val == this.SHORTENER_IDLE_STR) {
      shortener.val(this.SHORTENER_IDLE_STR);
      shortener.attr('style', 'color: #aaa;');
      this.hideButton();
    } else {
      this.showButton();
    }
  },

  changed: function(e) {
    var shortener = $("#shortener_area input");
    var val = shortener.val();
    tweetManager.composerData.urlShortener = val;
    if($.trim(val) != '') {
      if(e.which == 13) { //Enter key
        this.shortenIt();
      } else {
        this.showButton();
      }
    } else {
      this.hideButton();
    }
  },

  shortenCurrentPage: function() {
    var _this = this;
    chrome.tabs.getSelected(null, function(tab) {
      var shortenerInput = $("#shortener_area input");
      shortenerInput.val(tab.url);
      _this.shortenIt({title: tab.title});
    });
  },

  shortenIt: function(context) {
    var shortenerInput = $("#shortener_area input");
    var longUrl = shortenerInput.val();
    this.shortenPage(longUrl, context);
  },

  shortenPage: function(longUrl, context) {
    $("#loading").show();
    var shortenerInput = $("#shortener_area input");
    shortenerInput.attr('disabled', 'disabled');
    this.hideButton();
    var _this = this;
    shortener.shorten(longUrl, function(success, shortUrl) {
      $("#loading").hide();
      shortenerInput.removeAttr('disabled');
      _this.closeArea();
      _this.clear();
      var textarea = $("#compose_tweet_area textarea");
      if(success && shortUrl) {
        var newText = textarea.val();
        if(newText.length > 0 && newText[newText.length - 1] != ' ') {
          newText += ' ';
        }
        if(context && context.title && OptionsBackend.get('share_include_title')) {
          shortUrl = context.title + ' - ' + shortUrl;
        }
        newText += shortUrl;
        textarea.val(newText);
        Composer.textareaChanged();
      } else if(!success) {
        Renderer.showError(shortUrl);
      }
      Composer.showComposeArea(true);
    });
  }
}

var Renderer = {
  getTimestampText: function (inputTimestampStr) {
    var inputTimestamp = Date.parse(inputTimestampStr);
    var nowTimestamp = new Date().getTime();

    var diff = (nowTimestamp - inputTimestamp) / 1000;
    if(diff < 15) {
      return "just now";
    } else if(diff < 60) {
      return "less than 1 minute ago";
    } else if(diff < 60 * 60) {
      var minutes = parseInt(diff / 60);
      return minutes + " minute" + ((minutes > 1) ? "s" : "") + " ago";
    } else if(diff < 60 * 60 * 24) {
      var hours = parseInt(diff / (60 * 60));
      return "about " + hours + " hour" + ((hours > 1) ? "s" : "") + " ago";
    } else if(diff < 60 * 60 * 24 * 30) {
      var days = parseInt(diff / (60 * 60 * 24));
      return "about " + days + " day" + ((days > 1) ? "s" : "") + " ago";
    } else if(diff < 60 * 60 * 24 * 30 * 12) {
      var months = parseInt(diff / (60 * 60 * 24 * 30));
      return "about " + months + " month" + ((months > 1) ? "s" : "") + " ago";
    } else {
      return "years ago";
    }
  },

  getTimestampAltText: function (inputTimestampStr) {
    var inputTimestamp = Date.parse(inputTimestampStr);
    return new Date(inputTimestamp).toLocaleDateString() + " " + new Date(inputTimestamp).toLocaleTimeString();
  },

  geoImage: function (aElement, lat, long, name) {
    var lat = lat.toFixed(6).toString().replace(".", "");
    var long = long.toFixed(6).toString().replace(".", "");
    var url = 'http://maps.google.com/mapdata?cc=EN&min_priority=1&w=160&h=160&latitude_e6=' + lat + '&longitude_e6=' + long + '&zm=2000&Point=b&Point.latitude_e6=' + lat + '&Point.longitude_e6=' + long + '&Point.iconid=33&Point=e';
    $(aElement).tipsy({
      title: function() {
        return '<img src="img/loading.gif" /> Loading map...';
      },
      image: url,
      html: true,
      showNow: true,
      opacity: 1.0,
      gravity: $.fn.tipsy.autoWE
    });
  },

  expandLink: function (aElement, url) {
    if(!OptionsBackend.get('show_expanded_urls')) {
      return;
    }
    var m = url.match(/http:\/\/(www\.)?(twitpic|twitgoo|yfrog|movapic).com\/(.*)/);
    if(m) {
      var srcUrl = null;
      if(m[2] == "twitpic" || m[2] == "twitgoo") {
        srcUrl = "http://" + m[2] + ".com/show/thumb/" + m[3];
      } else if(m[2] == "yfrog") {
        srcUrl = "http://yfrog.com/" + m[3] + ".th.jpg";
      } else if(m[2] == "movapic") {
        var iid = m[3].split(/\//)[1];
        srcUrl = "http://image.movapic.com/pic/t_" + iid + ".jpeg";
      }
      if(!srcUrl) {
        return;
      }
      $(aElement).tipsy({
{'fraction_non_alphanumeric': 0.17465895953757227, 'fraction_numerical': 0.0067976878612716765, 'mean_word_length': 3.003610108303249, 'pattern_counts': {'":': 8, '<': 85, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '851771', 'n_tokens_mistral': 14269, 'n_tokens_neox': 13917, 'n_words': 2437}