/*
 * twitter_identica - A program to combine twitter and laconica feeds
 * 
 * @fileOverview A script to combine multiple twitter and laconica feeds.
 * @author <a href="mailto:gavin.kinsey@gmail.com">Gavin Kinsey</a>
 * @version 1.1
 * 
 * Copyright (c) 2009 Gavin Kinsey
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 * 
 */



/// @description Array to store the tweets in
var tweets = new Array();

/// @description Track which feed to pull from
var callCount = 0;



/**
 * @description Convert a time string to the age of the tweet
 * @param time The time string
 * @returns The age
 */
function dateToAge(time)  {
   var month = 1000 * 60 * 60 * 24 * 30;
   var week = 1000 * 60 * 60 * 24 * 7;
   var day = 1000 * 60 * 60 * 24;
   var hour = 1000 * 60 * 60;
   var minute = 1000 * 60;
   var second = 1000;
   
   var now = new Date();
   var then = new Date();
   then.setTime(Date.parse(time));

   var diff = now - then;
   var text = '';
   
   if (diff > month)  {
      text = Math.floor(diff / month) + ' months';
   }
   else if (diff > week)  {
      text = Math.floor(diff / week) + ' weeks';
   }
   else if (diff > day)  {
      text = Math.floor(diff / day) + ' days';
   }
   else if (diff > hour)  {
      text = Math.floor(diff / hour) + ' hours';
   }
   else if (diff > minute)  {
      text = Math.floor(diff / minute) + ' minutes';
   }
   else  {
      text = Math.floor(diff / second) + ' seconds';
   }
   text += ' ago';
   
   return text;
}


/**
 * @description Make a JSON call
 * @param Url of handler to call
 * @param Event to call when complete
 * @param Event to call when an error is encountered
 */
function reqJSON(url, success, error) 
{
   var CallParams = { };
   CallParams.type = "GET";
   CallParams.url = url;
   //CallParams.username = username;
   //CallParams.password = password;
   CallParams.processData = true;
   //CallParams.cache = false;
   CallParams.dataType = "json";
   CallParams.success = success;
   if (error)  {
      CallParams.error = error;
   }
   $.ajax(CallParams);
}


/**
 * @description Compare two tweets based on their timestamps
 * @param a First tweet
 * @param b Second tweet
 * @returns -1 if a is newer than b else 1
 */
function sortTweets(a, b)
{
   var timea = new Date();
   var timeb = new Date();
   timea.setTime(Date.parse(a.created_at));
   timeb.setTime(Date.parse(b.created_at));
   
   if (timea > timeb)  {
      return -1;
   }
   else  {
      return 1;
   }
}


/**
 * @description Strip off the end of a URL to get the site address
 * @param fullurl The URL http://www.example.com/some/other/text
 * @returns http://www.example.com/
 */
function getBaseUrl(fullurl)
{
   var stripped = '';
   if (fullurl.substr(0, 8) == 'https://')  {
      stripped = fullurl.substring(8);
   }
   else  {
      stripped = fullurl.substring(7);
   }
   var endIndex = stripped.search('/');
   stripped = stripped.substr(0, endIndex);
   
   return stripped;
}


/**
 * @description Go through all the existing tweets and check if the new one 
 *              is there already
 * @param oldTweets An array of all the existing tweets
 * @param newTweet The new tweet
 * @returns true or false
 */
function checkForDups(oldTweets, newTweet)
{
   var dupe = false;
   $.each(oldTweets, function(i, tweet)  {
      if (tweet.text == newTweet.text)  {
         dupe = true;
      }
   });
   return dupe;
}
   

/**
 * @description Search the text for links and make them clickable
 * @param startMarker Text to look for that indicates a link
 * @param text The original text
 * @param prefix Text to put in front of the URL
 * @returns Text with links
 */
function addLink(startMarker, text, prefix)
{
   var endindex = 0;
   while (endindex < text.length)  {
      startindex = text.indexOf(startMarker, endindex);
      if (startindex >= 0)  {
         endindex = text.indexOf(' ', startindex);
         if (endindex < 0)  {
            endindex = text.length;
         }
         before = text.substring(0, startindex);
         url = text.substring(startindex, endindex);
         after = text.substring(endindex);
         href = url.link(prefix + url.replace('@', ''));
         text = before + href + after;
         endindex = before.length + href.length
      }
      else  {    
         break;
      }
   }
   return text;
}


/**
 * @description Convert http https and @ replies to links
 * @param text The original text
 * @param baseUrl Site the tweet came from (to use for @s)
 * @returns Text with links
 */
function addLinks(text, baseUrl)
{
   text = addLink('https://', text, '');
   text = addLink('http://', text, '');
   text = addLink('@', text, baseUrl);
   return text
}


function escapeHTML(text)
{
   var escaped = text;
   escaped = escaped.replace(/&/g, '&amp;');
   escaped = escaped.replace(/</g, '&lt;');
   escaped = escaped.replace(/>/g, '&gt;');
   escaped = escaped.replace(/\"/g, '&quot;');
   escaped = escaped.replace(/\'/g, '&apos;');
   return escaped;
}


/**
 * @description JSON request succeeded, 
 *              process the data and insert it into the web page
 * @param json The json data received
 * @param textStatus Result code
 */
function readJson(json, textStatus) 
{
   //Successful call
   //Do stuff with the JSON
   //mb.append('Got json data ' + json.length + '<br />');
   //mb.append(textStatus);
   
   var requestUrl = this.url;
   var baseUrl = getBaseUrl(requestUrl);
   
   // Clear out any old tweets from the html
   $("p.tweet").remove();
   
   // Delete old tweets from this url from the list
   var oldtweets = tweets;
   tweets = new Array();
   $.each(oldtweets, function(i, item)  {
      if (item.baseUrl != baseUrl)  {
         tweets[tweets.length] = item;
      }
   });
   
   // Add newly retrieved tweets to the list
   $.each(json, function(i, item)  {
      item.baseUrl = baseUrl;
      if (checkForDups(tweets, item) == false)  {
         tweets[tweets.length] = item;
      }
   });
   
   // Sort the tweet list by age
   tweets.sort(sortTweets);
   
   // Print the tweets to the html
   var pretext = '<p class="tweet">';
   var postext = '</p>';
   $.each(tweets, function(i, item)  {
      //pretext = '<p class="tweet ';
      //pretext = pretext + item.baseUrl.replace('.', '') + '">';
      var ago = dateToAge(item.created_at);
      var base = 'http://' + item.baseUrl + '/';
      var text = escapeHTML(item.text);
      text = addLinks(text, base);
      var userlink = item.user.screen_name.link(base + item.user.screen_name);
      mb.append(pretext + ago + ': ' + userlink + ': ' + text + postext);
   });
}


/**
 * @description Called if JSON request failed
 * @param XMLHttpRequest
 * @param textStatus
 * @param errorThrown
 */
function failJson(XMLHttpRequest, textStatus, errorThrown) 
{
   // typically only one of textStatus or errorThrown 
   // will have info
   // 
   mb.append("Error getting json data<br />");
}


/**
 * @description Main function
 */
function display() {
   mb = $("#microblog");
   //mb.append("Start<br />");
    
   var urls = [ "https://identi.ca/api/statuses/friends_timeline.json?callback=?",
                "https://twitter.com/statuses/friends_timeline.json?callback=?"
               ];
   //var urls = [ "identica_friends.json",
   //             "twitter_friends.json"
   //            ];
   
   //if ( 0 == $("p.tweet").length )  {
   //   $.each(urls, function(i, url)  {
   //      reqJSON(url, readJson, failJson);
   //   });
   //}
   //else  {
   if (callCount < urls.length)  {
      reqJSON(urls[callCount], readJson, failJson);
      callCount = callCount + 1;
   }
   else  {
      callCount = 0;
   }
   //}
}
