$(function() {
   $("#yoinkByTweeter").click(yoinkByTweeter);
   $("#yoinkByQuery").click(yoinkByQuery);
   $("#twitterID").keyup(function(e) {
     var key = e.charCode || e.keyCode || 0;
     if (key==13) yoinkByTweeter();
    });
   $("#query").keyup(function(e) {
     var key = e.charCode || e.keyCode || 0;
     if (key==13) yoinkByQuery();
    });
   $("#userInput td input").focus(function(e) {
     autoSelect(this);
   });
   $("#showHTML").click(showHTML);
   $("#showText").click(showText);
   $("#clear").click(function() {
     var size = $("#faves li").length;
     $("#faves ul").empty();
     $("#timeline li").removeClass("selected");
     growlMessage("Removed", size);
     onFavesChanged();
   });
   $("#copyAll").click(function() {
     var count = 0;
     $("#timeline li").each(function() {
       var added = makeFaveEl($(this));
       if (added) count++;
     });
     growlMessage("Added", count);
     onFavesChanged();
   });
   $("#faves ul").sortable();
   // $("#timeline ul").sortable({ connectWith: "#faves ul"});
});

function yoinkByTweeter() {
  $("#userInput td input").removeClass("highlighted");
  $("#twitterID").addClass("highlighted");
   yoink("http://twitter.com/status/user_timeline/"+$("#twitterID").val()+".json?count=200&callback=?",
    false,
    function(response) { return response; },
    function(tweet) {
      return linkify(tweet.text)
      + " <span class='createdAt'>"  
      + relative_time(tweet.created_at)  
      + "</span><span class='client'> via "  
      + unlinkify(tweet.source)
      + "</span>"
    }); 
}

function yoinkByQuery() {
  $("#userInput td input").removeClass("highlighted");
  $("#query").addClass("highlighted");
   yoink("http://search.twitter.com/search.json?q="+$("#query").val()+"&rpp=100&callback=?",
    true,
    function(response) { return response.results; },
    function(tweet) {
      return linkify(tweet.text)
      + " <span class='createdAt'>"+relative_time(tweet.created_at)+"</span>"
      + " <span class='meta'>by <a class='twitterUser' target='twitlinks' href='http://twitter.com/"+tweet.from_user+"'>"
          + "@" + tweet.from_user+"</a></span>";
    }); 
}

function yoink(apiURL, userMatters, extractor, tweetHTMLizer) {

  $("#userInput").animate({marginTop: "0.5em", fontSize: "0.8em" }, 1200, "swing");
  $("#heading img").animate({width: "400px", height: "80px" });
  $("#explanation").slideUp();

  $("#timeline, #faves").show(); // for first time
  $("#progress").show();
  // $("#timeline ul, #faves ul").empty();
  $("#timeline ul").empty();
  // $("#timeline ul").fadeOut().empty().show();
  // Twitter handling http://ralphwhitbeck.com/2007/11/20/PullingTwitterUpdatesWithJSONAndJQuery.aspx
  $.getJSON(apiURL, function(data, textStatus) { 
     $("#progress").hide();
     $("#faves").fadeIn();
     $.each(extractor(data), function(i, tweet) { 
         tweet.userMatters = userMatters;
         convertToTimelineFormat(tweet);
         // $("img#profile").attr("src", item.user["profile_image_url"]);  
         $("#timeline ul").append(makeTimelineEl(tweet).html(tweetHTMLizer(tweet)));
     });
   }); 
}

function makeTimelineEl(tweet) {
  return $("<li>").data(
    "tweet", tweet
  ).click(function() {
    var added = makeFaveEl($(this));
    if (!added) removeFromFavesByID($(this).data("tweet").id);
    // onFavesChanged();
  });
}

function makeFaveEl(timelineEl) {
    var tweetID = timelineEl.data("tweet").id;
    var found = false;
    $("#faves li").each(function() {
      if ($(this).data("tweet").id==tweetID) { found=true; return false; }
    });
    if (found) {
      // removeFromFavesByID(timelineEl.data("tweet").id);
      return false;
    } else {
      timelineEl.flashIn().addClass("selected");
      $("<li>").data(
        "tweet", timelineEl.data("tweet")
      ).append(
        timelineEl.html()
      ).append(
        " "
      ).append(
        $("<button>").html("Remove")
                     .click(function() {
                       var tweetEl = $(this).parent();
                       removeFromFaves(tweetEl);
                    })
      ).appendTo($("#faves ul"));
      onFavesChanged();
      return true;
  }
}

function removeFromFavesByID(tweetID) {
  $("#faves li").each(function() {
    if ($(this).data("tweet").id == tweetID) {
      removeFromFaves($(this));
      onFavesChanged();
      return false;
    }
  });
}

function removeFromFaves(tweetEl) {
  var tweetID = tweetEl.data("tweet").id;
  tweetEl.remove();
  $("#timeline li").each(function() {
    if ($(this).data("tweet").id == tweetID) {
      $(this).removeClass("selected").flashOut();
    }
  });
  onFavesChanged();
}

function onFavesChanged() {
  if ($("#faves li").length==0) {
    $("#filledInstruction").hide();
    $("#emptyInstruction").show();
  } else {
    $("#filledInstruction").show();
    $("#emptyInstruction").hide();
  }
}

function showHTML() {
  showPopup(
    function(html) {
      return "&lt;ul&gt;<br/>" + html + "&lt;/ul&gt;";
    },
  function(tweet) {
    return "&lt;li&gt;"+linkifyHTML(tweet.text)+"<br/>"
      + tweet.created_at + (tweet.userMatters ? (" from " + tweet.user.name) : "")
      + "&lt;/li&gt;"
  });
}

function showText() {
  showPopup(
    function(html) {
      return html;
    },
    function(tweet) {
      var tweeter = (tweet.from_user||tweet.user.name)
      return "* "+tweet.text+"<br/> "
        + tweet.created_at + (tweet.userMatters ? "" : " from " +  tweeter)+"<br/>"
        + " (http://twitter.com/statuses/"+tweet.id
        + (tweet.userMatters ? " http://twitter.com/"+tweeter : "")
        + ")"
    }
  );
}

function showPopup(popupDecorator, popupTweetHTMLizer) {
  var html="";
  $("#faves li").each(function() {
    if (html.length) html+="&nbsp;<br/>";
    var tweet = $(this).data("tweet");
    html += popupTweetHTMLizer(tweet) + "<br/>";
  });
  html = "<div id='code'>" + popupDecorator(html) + "</div>";
  $.nyroModalManual({
    bgColor: '#3333cc',
    content: html,
    endShowContent: function() {
      autoSelect($("#code").get()[0]);
    }
  });
}

function linkify(text) {
      var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/i;
      return text.replace(exp,"<a target='twitlinks' href='$1'>$1</a>"); 
}

function unlinkify(html) {
      return html.replace(/<a href=.*?>(.*?)<\/a>/i, "$1");
}

// http://stackoverflow.com/questions/37684/replace-url-with-html-links-javascript
function linkifyHTML(text) {
      var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/i;
      return text.replace(exp,"&lt;a href='$1'&gt;$1&lt;/a&gt;"); 
}

// neutralises tweet data
function convertToTimelineFormat(tweet) {
  // SEARCH FORMAT
  //  0   1   2   3      4      5
  // Tue, 02 Jun 2009 21:25:53 +0000
  //
  // TIMELINE FORMAT
  //  0   1  2  3  4  5  6     7
  // Sun Apr 19 20:22:39 +0000 2009 
  //  0   2   1    4       5   3
  var values = tweet.created_at.split(" ");
  if (/[A-Z][a-z][a-z],/.test(values[0])) {
    tweet.created_at = values[0].replace(",","") + " " + values[2] + " " + values[1] + " " + values[4] + " " + values[5] + " " + values[3];
  }

  if (tweet.from_user) {
    tweet.user = {
      name: tweet.from_user
    };
  }

}

  function relative_time(time_value) {
    var values = time_value.split(" ");
    time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
    var parsed_date = Date.parse(time_value);
    var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
    var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
    delta = delta + (relative_to.getTimezoneOffset() * 60);
    
    var r = '';
    if (delta < 60) {
      r = 'a minute ago';
    } else if(delta < 120) {
      r = 'couple of minutes ago';
    } else if(delta < (45*60)) {
      r = (parseInt(delta / 60)).toString() + ' minutes ago';
    } else if(delta < (90*60)) {
      r = 'an hour ago';
    } else if(delta < (24*60*60)) {
      r = '' + (parseInt(delta / 3600)).toString() + ' hours ago';
    } else if(delta < (48*60*60)) {
      r = '1 day ago';
    } else {
      r = (parseInt(delta / 86400)).toString() + ' days ago';
    }
    
    return r;
}

// http://www.matts411.com/post/auto_selecting_text/
var autoSelect = function (el) {
  if (/textarea/i.test(el.tagName) || (/input/i.test(el.tagName) && /text/i.test(el.type))) {
    el.select();
  } else if (!!window.getSelection) { // FF, Safari, Chrome, Opera
    var sel = window.getSelection();
    var range = document.createRange();
    range.selectNodeContents(el);
    sel.removeAllRanges();
    sel.addRange(range);
  } else if (!!document.selection) { // IE
    document.selection.empty();
    var range = document.body.createTextRange();
    range.moveToElementText(el);
    range.select();
  }
};

jQuery.fn.flashIn = function() {
  var delay = 100;
  $(this).fadeOut(delay).fadeIn(delay).fadeOut(delay).fadeIn(delay);
  return $(this);
}

jQuery.fn.flashOut = function() {
  // var delay = 100;
  // $(this).fadeOut(delay).fadeIn(delay).fadeOut(delay).fadeIn(delay);
  $(this).fadeOut(100).fadeIn(300);
  return $(this);
}

jQuery.fn.log = function() {
  if (console) console.log.apply(console, [x=this].concat(arguments));
  return this;
}

function log() {
  if (console && console.log) console.log.apply(console, arguments);
}

function growlMessage(verb, quantity) {
  $.jGrowl(verb + " " + quantity + " tweet" + (quantity==1?"":"s"), { life: 500});
}
