(function () {
    /** Private variables */
    var browser = (function() {
    	var b = navigator.userAgent.toLowerCase();

    	// Figure out what browser is being used
    	return {
    		safari: /webkit/.test(b),
    		opera: /opera/.test(b),
    		msie: /msie/.test(b) && !(/opera/).test(b),
    		mozilla: /mozilla/.test(b) && !(/(compatible|webkit)/).test(b)
    	};
    })();

    var twitterTarget = null;
    var twitterOptions = {};
    
    
    /** Global functions */
    
    // to create a public function within our private scope, we attach the 
    // the function to the window object
    window.twitterCallback = function (obj) {
        // private shortcuts
        function node(e) {
            return document.createElement(e);
        }
        
        function text(t) {
            return document.createTextNode(t);
        }

        var target = document.getElementById(twitterTarget);
        var ul = node('p'), strong, statusSpan, timeSpan, i, max = obj.length > twitterOptions.count ? twitterOptions.count : obj.length;

        for (i = 0; i < max; i++) {
            if (twitterOptions.ignoreReplies && obj[i].text.substr(0, 1) == '@') {
                continue; // skip
            }
            
            strong = node('strong');
            statusSpan = node('span');
            statusSpan.className = 'twitterStatus';
            timeSpan = node('span');
            timeSpan.className = 'twitterTime';
            statusSpan.innerHTML = obj[i].text; // forces the entities to be converted correctly

            if (twitterOptions.enableLinks == true) {
                statusSpan.innerHTML = statusSpan.innerHTML.linkify();
            }

            timeSpan.innerHTML = relative_time(obj[i].created_at);

            

            strong.appendChild(statusSpan);
            strong.appendChild(text(' '));
            strong.appendChild(timeSpan);
            ul.appendChild(strong);
        }

        if (twitterOptions.clearContents) {
            while (target.firstChild) {
                target.removeChild(target.firstChild);
            }
        }

        target.appendChild(ul);
    };
    
    window.getTwitters = function (target, id, count, options) {
        if (typeof id == 'object') {
            options = id;
            id = options.id;
            count = options.count;
        } 

        if (!count) count = 1;
        
        if (options) {
            options.count = count;
            if (options.ignoreReplies && count == 1) {
                count = 2;
            }
        }

        // need to make these global since we can't pass in to the twitter callback
        twitterTarget = target;
        twitterOptions = options;

        ready(function() {
            var url = 'http://www.twitter.com/statuses/' + (options.withFriends ? 'friends_timeline' : 'user_timeline') + '/' + id + '.json?callback=twitterCallback&count=' + count;

            var script = document.createElement('script');
            script.setAttribute('src', url);
            document.getElementsByTagName('head')[0].appendChild(script);
        });
    };

    /** Private functions */

    // ready and browser adapted from John Resig's jQuery library (http://jquery.com)
    function ready(callback) {
        if ( browser.mozilla || browser.opera ) {
            document.addEventListener( "DOMContentLoaded", callback, false );
        } else if ( browser.msie ) {
            // If IE is used, use the excellent hack by Matthias Miller
            // http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited

            // Only works if you document.write() it
            document.write("<scr" + "ipt id=__ie_init defer=true src=//:><\/script>");

            // Use the defer script hack
            var script = document.getElementById("__ie_init");

            // script does not exist if jQuery is loaded dynamically
            if (script) {
                script.onreadystatechange = function() {
                    if ( this.readyState != "complete" ) return;
                    this.parentNode.removeChild( this );
                    callback.call();
                };
            }

            // Clear from memory
            script = null;

            // If Safari  is used
        } else if ( browser.safari ) {
            // Continually check to see if the document.readyState is valid
            var safariTimer = setInterval(function () {
                // loaded and complete are both valid states
                if ( document.readyState == "loaded" || 
                document.readyState == "complete" ) {

                    // If either one are found, remove the timer
                    clearInterval( safariTimer );
                    safariTimer = null;
                    // and execute any waiting functions
                    callback.call();
                }
            }, 10);
        }
    }
    
    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 = 'WDC said less than a minute ago via Twitter';
        } else if(delta < 120) {
            r = 'WDC said a minute ago via Twitter';
        } else if(delta < (45*60)) {
            r = (parseInt(delta / 60)).toString() + ' minutes ago via Twitter';
        } else if(delta < (90*60)) {
            r = 'WDC said an hour ago via Twitter';
        } else if(delta < (24*60*60)) {
            r = 'WDC said ' + (parseInt(delta / 3600)).toString() + ' hours ago via Twitter';
        } else if(delta < (48*60*60)) {
            r = 'WDC said 1 day ago via Twitter';
        } else {
            r =  'WDC said ' + (parseInt(delta / 86400)).toString() + ' days ago via Twitter';
        }
        return r;
    }

    String.prototype.linkify = function() {
        return this.replace(/[A-Za-z]+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+/, function(m) {
            return m.link(m);
        });
    };
})();						