//////////////////////////////////////////////////////////////
// Moby backchannel 0.5

// Variables (use the settings block to tweak)
var faviUrls = new Array();
// all fetched favicons and corresponding urls (cache)
var fetchFaviBussy = false;
// is the favicon service bussy ?

var uniqueIdCounter = 0;
// for unique number generation
var timeCorrection = 0;
// Seconds the servertime differs from the user

var textData = new Array();
// Tweet db
var textLastUpdate = 0;
// Time last recieved tweet
var textBannedIDs = "";
// Banned tweet IDs, these dont show up on the screen
var textShownIDs = "";
// Shown tweet IDs, these dont show up on the screen (prevent showing double tweets)
var textReshowTime = 60;
// Reshow tweets after no new tweet is present for xx seconds
var textConfig = new Array();
// textStreams configuration
var textIDs = new Array();
// The textIDs currently on the screen
var textIDcounter = 0;
// number of tweets on the screen
var textBannedUsers = new Array('TobiasdeWit', 'securitymax', 'twithit', 'GlamourGear', 'ChartingStock');
// banned twitter users (spammers)

var mobyData = new Array();
// Moby db
var mobyConfig = new Array();
// mobyStreams configuration
var mobyFirstLoad = true;
// Check if this is the first moby shown
var mobyLastUpdate = 0;
// Time last shown moby
var mobyBannedIDs = "";
// All banned moby's
var mobyIDs = new Array();
// moby's currently on the screen
var mobyIDcounter = 0;
// number of moby's on the screen
var mobyMemory = "";
// moby image to remember for thumnail display
var mobyCurrentMem = - 1;
// unique number counter for thumnail identification

var mobyStaticConfig = new Array() // Configuration for static pictures in the moby stream
var mobyStaticTimeout = 90;
// time between moby's to allow two static images in a row
var mobyStaticLastUpdate = 0;
// when last static picture has been shown
var mobyLastStatic = false;
// to remember if the last picture was a static picture
var mobyStaticMinimalInterval = 30;
// minimal time between static images
var mobyScrollPreIterator = 0;
// counter to limit preload iterations
var mobyScrollPreloader;
// preload object for images
var mobyRandomData = new Array();
// Moby db for random images
var mobyRandomShownData = new Array();
// Moby db for random images already shown

var mobyPauseScreen = false;
// show the pause screen
var mobyPauseTime = 40;
// time after the pause screen has te be shown
var mobyPauseIsShown = false;
// remember if pause screen is currently displayed


// Startup the backchannel
// -----------------------------------------------------------

// set the time correction between client and server
setTimeCorrection();

// Preload common favicons
fetchFavicon("http://www.mobypicture.com/");
fetchFavicon("http://www.tinyurl.com/");
fetchFavicon("http://www.bit.ly/");


// kickstart the page when the document is ready
$(document) .ready(function () {
    // set the right style
    style_all();
    
    // remove function tweets (ban a tweet)
    $(".textBlock") .live('dblclick', function () {
        $(this) .hide(function () {
            textBan($(this) .children('.tweetID') .val());
            $(this) .remove();
        });
    });
    
    // restyle the headers (detect hashtags and twitterusernames)
    $("#HeaderContent") .html(autoStyle($("#HeaderContent") .html()));
    
    // do not allow link clicking in the text stream
    $("#textContent a") .live('click', function () {
        return false;
    })
    
    // Start the text dataLoader
    textDataLoader();
    mobyDataLoader();
    
    // Start the fancyTime service (auto updates times on screen)
    fancyTime_Service();
    
    // Hide loading messages
    $("#TextLoader, #MobyLoader") .fadeOut(1000, function () {
        $(this) .remove();
    });
    
    // Start the scrollers after 2,5 seconds
    setTimeout('textScroller()', 2500);
    setTimeout('mobyScroller()', 2500);
});

// resize the elements to the correct size when the window resizes
$(window) .resize(function () {
    style_all();
});


// Tools
// -----------------------------------------------------------

// simple array removal
Array.prototype.remove = function (from, to) {
    var rest = this .slice((to || from) + 1 || this .length);
    this .length = from < 0 ? this .length + from : from;
    return this .push.apply(this, rest);
};

// trim function for strings
String.prototype.trim = function () {
    return this .replace(/^\s + |\s + $/g, "");
}

// preload images
jQuery.preloadImages = function () {
    for (var i = 0; i < arguments.length; i++) {
        jQuery("<img>") .attr("src", arguments[i]);
    }
}

// preload images and attach to specific element to remove it later
jQuery.preloadMoby = function () {
    for (var i = 0; i < arguments.length; i++) {
        jQuery("<img>") .attr("src", arguments[i]) .appendTo("#ImagePreloader");
    }
}

// calculates the time difference with the server in seconds
function setTimeCorrection() {
    $.get("/ajax.php?action=gmtTime", function (data) {
        timesince = timeGMT();
        
        fTime = new Date(data);
        sTime = new Date(timesince);
        
        timeCorrection = Math.floor((fTime.getTime() - sTime.getTime()) / 1000);
    })
}

// Generate a unique id
function uniqueId() {
    uniqueIdCounter++;
    return uniqueIdCounter;
}

// autolink urls in text
function autolink(s) {
    s = " " + s + " ";
    s = s.replace(" www.", "http://www.");
    s = s.replace("http://", " http://");
    s = s.replace("  ", " ");
    
    var hlink = /\s(ht|f) tp:\/\/([^ \, \; \:\ ! \) \(\"\'\ < \ > \f\n\r\t\v]) + /g;
    return (s.replace(hlink, function ($0, $1, $2) {
        s = $0.substring(1, $0.length);
        // remove trailing dots, if any
        while (s.length > 0 && s.charAt(s.length - 1) == '.')
        s = s.substring(0, s.length - 1);
        // add hlink
        return " " + s.link(s);
    }));
}

// find @username and #hashtag and style them
function autoStyle(text) {
    tags = new Array();
    users = new Array();
    
    text = text.replace(")", " ) ") .replace("(", " ( ") .replace(".", " . ") .replace(",", " , ");
    words = text.split(" ");
    
    $.each(words, function (i, word) {
        firstletter = word.substr(0, 1);
        
        if (firstletter == "#")
        tags[tags.length] = word; else if (firstletter == "@")
        users[users.length] = word;
    });
    
    text = " " + text + " ";
    
    $.each(tags, function (i, tag) {
        text = text.replace(" " + tag + " ", " <span class='hashTag'>" + tag + "</span> ")
    });
    
    $.each(users, function (i, user) {
        text = text.replace(" " + user + " ", " <span class='twitterUser'>" + user + "</span> ")
    });
    
    text = text.replace(" ) ", ")") .replace(" ( ", "(") .replace(" . ", ".") .replace(" , ", ",") .replace(/&amp; /gi, "&");
    text = text.trim();
    
    return text;
}

// check if image object is loaded
function imageLoaded(img) {
    if (! img.complete)
    return false;
    
    if (typeof img.naturalWidth != "undefined" && img.naturalWidth == 0)
    return false;
    
    return true;
}

// get the current time in GMT
function timeGMT() {
    tempTime = new Date();
    
    if (timeCorrection != 0)
    tempTime.setTime(tempTime.getTime() + (timeCorrection * 1000));
    
    gmtMs = tempTime.toGMTString();
    
    return gmtMs;
}

// get a user-friendly time format
function niceTime(time, timesince) {
    if (time === undefined)
    return " ";
    
    if (timesince === undefined)
    timesince = timeGMT();
    
    fTime = new Date(time);
    sTime = new Date(timesince);
    
    timeDif = Math.floor((sTime.getTime() - fTime.getTime()) / 1000);
    
    if (timeDif < 60)
    return timeDif + ' seconds ago'; else if (timeDif < 120) {
        minutecount = Math.floor(timeDif / 60);
        if (minutecount == 1)
        return '1 minute ago'; else
        return minutecount + ' minutes ago';
    } else if (timeDif < 3600)
    return Math.floor(timeDif/60) + ' minutes ago'; else if (timeDif < 86400) {
        hourcount = Math.round(timeDif / 3600);
        if (hourcount == 1)
        return '1 hour ago'; else
        return hourcount + ' hours ago';
    } else if (timeDif < 259200) {
        dayCount = Math.floor(timeDif / 86400);
        if (dayCount == 1)
        return '1 day ago'; else
        return dayCount + ' days ago';
    } else {
        return time;
    }
    
    return time;
}

// Tools: favicon functions

// get only the domain+tld
function stripDomain(url) {
    stripedUrl = url.replace("http://", "");
    stripedUrl = stripedUrl.replace("www.", "");
    slashPos = stripedUrl.search("/");
    
    if (slashPos != - 1) {
        stripedUrl = stripedUrl.substring(0, slashPos);
    }
    
    return stripedUrl;
}

// get the position for a url in the favicon cache
function getFaviconID(url) {
    stripedUrl = stripDomain(url);
    
    faviID = - 1;
    $.each(faviUrls, function (i, item) {
        if (item[0] == stripedUrl) {
            faviID = i;
            return faviID;
        }
    });
    
    return faviID;
}

// fetch an iconlocation to the local cache
function fetchFavicon(url) {
    // check if icon is already present in cache
    faviID = getFaviconID(url);
    
    // if favicon isnt know, qeue it for download
    if (faviID == - 1)
    faviconFetchService(url);
}

// favicon Fetch Service, downloads favicons and places it in cache
function faviconFetchService(url) {
    // only one fetch at the time, or it will becoume favicon soup
    if (fetchFaviBussy) {
        // TODO: add code to deny double service requests
        setTimeout('faviconFetchService("' + url + '")', 600);
    } else {
        fetchFaviBussy = true;
        if (getFaviconID(url) != - 1) {
            // faviIcon has already been found
            fetchFaviBussy = false;
        } else {
            $.get("/ajax?action=favicon&callback=?", {
                request_url: url
            },
            function (data) {
                if (data.favicon != "") {
                    // Save the new favicon
                    faviID = faviUrls.length;
                    faviUrls[faviID] = new Array();
                    faviUrls[faviID][0] = stripDomain(url);
                    // Domain shortcode
                    faviUrls[faviID][1] = data.favicon; // Domain favicon
                    
                    // preload favicon
                    $.preloadImages(data.favicon);
                }
                
                // release favicon service
                fetchFaviBussy = false;
            },
            'json');
        }
    }
}

// get a favicon location from the local cache
function getFavicon(url) {
    faviID = getFaviconID(url);
    
    if (faviID == - 1)
    return false; else
    return faviUrls[faviID][1];
}

// strip urls from text and fetch favicons
function preloadFavicons(text) {
    // detect links
    linkedtext = "<div>" + autolink(text) + "</div>";
    
    // find the links and fetch the favicons
    $(linkedtext) .find("a") .each(function (i, item) {
        fetchFavicon($(this) .attr("href"));
    });
}


// Tools: style handlers
function style_all() {
    style_smallImages();
    style_bigImages();
}

function style_smallImages() {
    $("#smallImages") .css('height', Math.ceil($("#mobyStream") .css('width') .replace("px", "") * 0.3));
}

tcounter = 0;
function style_bigImages() {
    pHeight = $(".mobycontent") .css('height');
    tcounter++;
    if (pHeight !== undefined) {
        pHeight = Math.ceil(pHeight.replace("px", ""));
        $('.mobycontent table, .mobycontent tr, .mobycontent td') .height(pHeight);
    }
}

// Time updater
// -----------------------------------------------------------
function fancyTime_Service() {
    try {
        currentTimeGMT = timeGMT();
        $(".fancyTime") .each(function () {
            originalDate = $(this) .find("input") .val();
            newTime = niceTime(originalDate, currentTimeGMT);
            $(this) .find("span") .html(newTime.replace(/ /g, '&nbsp;'));
        });
    }
    catch (err) {
    }
    
    setTimeout('fancyTime_Service()', 1000);
}


// Text stream
// -----------------------------------------------------------

// loads data for the text feed
function textDataLoader() {
    // fetch all configured sources
    $.each(textConfig, function (i, item) {
        try {
            switch (item.type) {
                case 'search' :
                textDataLoader_TwitterSearch(i);
                break;
                case 'user' :
                textDataLoader_TwitterUser(i);
                break;
            }
        }
        catch (err) {
        }
    });
    
    // Check if tweets have to be shown again (if no new content is available reshow old tweets)
    if (textReshowTime != 0 && textLastUpdate != 0) {
        currentTime = new Date();
        if ((currentTime.getTime() - textLastUpdate) / 1000 >= textReshowTime && textData.length <= 1) {
            textShownIDs = '';
            $.each(textConfig, function (i, item) {
                item.lastID = 0;
            });
        }
    }
    
    // Recheck after a few seconds depending on the tweets queued
    if (textData.length < 4) {
        // check text feeds again after 30 seconds
        setTimeout('textDataLoader()', 30000);
    } else {
        // check text feeds again after 50 seconds
        setTimeout('textDataLoader()', 50000);
    }
}

// Add a text stream to the configuration
function AddTextStream(type, keywords, extra) {
    confPos = textConfig.length;
    textConfig[confPos] = new Object;
    textConfig[confPos].type = type;
    textConfig[confPos].keywords = keywords;
    textConfig[confPos].lastID = 0;
    
    if (extra === undefined)
    textConfig[confPos].extra = ''; else
    textConfig[confPos].extra = extra;
    
    if (type == 'feed')
    textDataLoader_Feed(confPos);
}


// Text stream: Data streams
// -----------------------------------------------------------

// add twittersearch results to stream (depricated)
function textDataLoader_TwitterSearch(instanceID) {
    textUrl = "http://search.twitter.com/search.json?callback=?";
    
    if (textConfig[instanceID].extra != '')
    extra = textConfig[instanceID].extra + "&"; else
    extra = '';
    
    if (textConfig[instanceID].lastID != 0)
    textUrl = "http://search.twitter.com/search.json?since_id=" + textConfig[instanceID].lastID + "&" + extra + "callback=?"; else
    textUrl = "http://search.twitter.com/search.json?" + extra + "callback=?";
    
    $.getJSON(textUrl, {
        q: textConfig[instanceID].keywords
    },
    function (data) {
        if (textConfig[instanceID].lastID != data.max_id && data.max_id != '-1') {
            textConfig[instanceID].lastID = data.max_id;
            $.each(data.results, function (i, item) {
                textAddData(item.id, item.text, item.created_at, item.from_user, item.profile_image_url);
            });
        }
    });
}

// add twitteruser results to stream (depricated)
function textDataLoader_TwitterUser(instanceID) {
    if (textConfig[instanceID].lastID != 0)
    textUrl = "http://twitter.com/statuses/user_timeline/" + textConfig[instanceID].keywords + ".json?since_id=" + textConfig[instanceID].lastID + "&callback=?"; else
    textUrl = "http://twitter.com/statuses/user_timeline/" + textConfig[instanceID].keywords + ".json?callback=?";
    
    $.getJSON(textUrl, function (data) {
        
        isFirst = true;
        
        $.each(data, function (i, item) {
            if (isFirst) {
                isFirst = false;
                textConfig[instanceID].lastID = item.id;
            }
            textAddData(item.id, item.text, item.created_at, item.user.screen_name, item.user.profile_image_url);
        });
    });
}

// add custom feed to stream
function textDataLoader_Feed(instanceID) {
    $.getJSON(textConfig[instanceID].keywords, {
        max_id: textConfig[instanceID].lastID
    },
    function (data) {
        updateTime = - 1;
        
        try {
            if (textConfig[instanceID].lastID != data.max_id && data.max_id != '-1') {
                textConfig[instanceID].lastID = data.max_id;
                $.each(data.results, function (i, item) {
                    textAddData(item.id, item.text, item.created_at, item.from_user, item.profile_image_url);
                });
            }
            
            timesince = timeGMT();
            
            fTime = new Date(data.next_update);
            sTime = new Date(timesince);
            
            updateTime = Math.floor((fTime.getTime() - sTime.getTime()) / 1000);
        }
        catch (err) {
        }
        
        if (updateTime < - 240)
        window.location.reload(); else if (updateTime == - 1)
        updateTime = 20; else if (updateTime < 2)
        updateTime = 2; else if (updateTime > 120)
        updateTime = 120;
        
        setTimeout('textDataLoader_Feed(' + instanceID + ')', (updateTime * 1000));
    });
}

// Text stream: Data tools
// -----------------------------------------------------------

// check if message is banned
function textIsBanned(id) {
    if (textBannedIDs.search(id) != - 1)
    return true; else
    return false;
}

// ban a message
function textBan(id) {
    textBannedIDs += '|' + id + '|';
}

// check if message has been shown already
function textIsShown(id) {
    if (textShownIDs.search(id) != - 1)
    return true; else
    return false;
}

// check if user is banned
function userIsBanned(user) {
    if (textBannedUsers.join() .toLowerCase() .search(user.toLowerCase()) != - 1)
    return true; else
    return false;
}

// mark a message as shown
function textMarkShown(id) {
    textShownIDs += '|' + id + '|';
}

// prepare data for stream and add it to the queue
function textAddData(id, text, date, user, avatarUrl) {
    // check if id isn't banned
    if (! textIsBanned(id) && ! textIsShown(id)) {
        textMarkShown(id);
        
        // tweets with moby's are shown in the mobystream
        if (text.search('http://mobypicture.com/?') != - 1)
        return;
        
        // check for banned users
        if (userIsBanned(user))
        return;
        
        // Update last update time
        currentTime = new Date();
        textLastUpdate = currentTime.getTime();
        
        // preload the favicons in the text
        preloadFavicons(text);
        
        // preload Avatar
        $.preloadImages(avatarUrl);
        
        // Decide the position in the stream (show older tweets before new tweets)
        dataPos = - 1;
        $.each(textData, function (i, item) {
            if (dataPos == - 1) {
                if (id > item.id) {
                    dataPos = i;
                }
            }
        });
        
        // if no position is found, add it to the end of the queue
        if (dataPos == - 1)
        dataPos = textData.length;
        
        newData = new Object;
        newData.id = id;
        newData.text = text;
        newData.date = date;
        newData.user = user;
        newData.avatarUrl = avatarUrl;
        
        textData.splice(dataPos, 0, newData);
    }
}


// Text stream: Animation methods (currently 1 availible)
// -----------------------------------------------------------

// iteration to show new tweets
function textScroller() {
    // Check if textData is present
    if (textData.length == 0) {
        setTimeout('textScroller()', 1500);
    } else {
        // get new textID position
        textIDcounter++;
        
        // store the textID
        textIDs[textIDs.length] = textIDcounter;
        
        // get the next text item
        textItem = textData[textData.length - 1];
        
        textItem.text = textItem.text + " ";
        
        if (textItem.date === undefined)
        textItem.date = new Date();
        
        sweetTime = niceTime(textItem.date, timeGMT());
        
        if (sweetTime === undefined)
        sweetTime = "";
        
        newTweet = $('<div class="textBlock hidden" id="tweet' + textIDcounter + '">' +
        '<input type="hidden" class="tweetID" value="' + textItem.id + '" />' +
        '<div class="textAvatar"><div class="textInfo"><span> @' + textItem.user + ' </span></div>' +
        '<div class="textInfo"><img src="' + textItem.avatarUrl + '" alt="" /></div>' +
        '<div class="textInfo"><span class="fancyTime"><input type="hidden" value="' + textItem.date + '" /><span>' + sweetTime.replace(/ /g, "&nbsp;") + '</span></span></div></div>' +
        '<div class="textContent"><span>' +
        autoStyle(autolink(textItem.text)) +
        '</span></div>' +
        '</div>');
        
        // TODO: create function for this
        // add favicons if posible
        newTweet.find("a") .each(function (i, textItem) {
            $(this) .attr("target", "_blank");
            favIcon = getFavicon($(this) .attr("href"));
            if (favIcon != false) {
                $(this) .html("<img src='" + favIcon + "' /> [link]");
            }
        });
        
        // add text to stream
        newTweet.prependTo("#textStream");
        
        // show animation
        $("#textStream .hidden") .slideDown(1000);
        
        //$("#textStream .hidden").animate({height: "block"}, { duration: 500, queue: false });
        
        // cleanup
        textData.remove(textData.length - 1);
        
        if (textIDs.length >= 20) {
            $("#tweet" + textIDs[0]) .remove();
            textIDs.remove(0);
        }
        
        // set the timeout for the textscroller depending on the number of tweets in the qeue
        if (textData.length > 70) {
            setTimeout('textScroller()', 500);
        } else if (textData.length > 50) {
            setTimeout('textScroller()', 1000);
        } else if (textData.length > 35) {
            setTimeout('textScroller()', 1500);
        } else if (textData.length > 20) {
            setTimeout('textScroller()', 2500);
        } else if (textData.length > 10) {
            setTimeout('textScroller()', 3500);
        } else if (textData.length > 5) {
            setTimeout('textScroller()', 6500);
        } else {
            setTimeout('textScroller()', 9500);
        }
    }
}

// -----------------------------------------------------------
// Moby stream
// -----------------------------------------------------------

// Add a moby stream to the configuration
function AddMobyStream(type, keywords) {
    confPos = mobyConfig.length;
    mobyConfig[confPos] = new Object;
    mobyConfig[confPos].type = type;
    mobyConfig[confPos].keywords = keywords;
    mobyConfig[confPos].lastID = 0;
}

// control data loading for the moby-feed
function mobyDataLoader() {
    // fetch all configured sources
    $.each(mobyConfig, function (i, item) {
        try {
            switch (item.type) {
                case 'feed' :
                mobyDataLoader_feed(i);
                break;
            }
        }
        catch (err) {
        }
    });
    
    currentTimeStamp = new Date();
    if (((currentTimeStamp - mobyLastUpdate) / 1000) > mobyPauseTime && mobyData.length == 0 && mobyLastUpdate != 0 && mobyPauseScreen)
    mobyPauseScreen_in();
    
    if (mobyData.length < 4) {
        // check moby feed again after 10 seconds
        setTimeout('mobyDataLoader()', 10000);
    } else {
        // check moby feed again after 30 seconds
        setTimeout('mobyDataLoader()', 30000);
    }
}

// Load the mobydata
function mobyDataLoader_feed(instanceID) {
    searchUrl = mobyConfig[instanceID].keywords + "?jsoncallback=?";
    
    $.getJSON(searchUrl, function (data) {
        currentTime = new Date();
        
        doCycle = false;
        
        try {
            if (mobyConfig[instanceID].lastID != data.items[0].id) {
                mobyResetID = mobyConfig[instanceID].lastID;
                mobyConfig[instanceID].lastID = data.items[0].id;
                doCycle = true;
            }
        }
        catch (err) {
        }
        
        if (doCycle) {
            $.each(data.items, function (i, item) {
                if (doCycle) {
                    if (mobyResetID == item.id) {
                        doCycle = false;
                        return;
                    } else {
                        addGlobalMoby_by_object(item);
                    }
                }
            });
        }
    });
}

// fetch function for random images in the mobyfeed
function mobyDataLoader_randomfeed(feed) {
    searchUrl = feed + "?amount=100&jsoncallback=?";
    
    $.getJSON(searchUrl, function (data) {
        $.each(data.items, function (i, item) {
            item = mobyPreloadObject(item);
            mobyRandomData.splice(mobyRandomData.length, 0, item);
        });
    });
}

// preload a moby object
function mobyPreloadObject(mobyObject) {
    $.preloadMoby(mobyObject.viewImage);
    $.preloadImages(mobyObject.avatar);
    return mobyObject;
}

// add a new picture by json object
function addGlobalMoby_by_object(mobyObject) {
    if (mobyObject.mediaType == 'audio')
    return;
    
    mobyObject = mobyPreloadObject(mobyObject);
    mobyObject.isStatic = false;
    
    dataPos = - 1;
    $.each(mobyData, function (i, item) {
        if (dataPos == - 1) {
            if (mobyObject.id > item.id) {
                dataPos = i;
            }
        }
    });
    
    // if no position is found, add it to the end of the queue
    if (dataPos == - 1)
    dataPos = mobyData.length;
    
    mobyData.splice(dataPos, 0, mobyObject);
}

// add an static image to the rotation
function addStaticMoby(title, image, pausetime) {
    currentTimeStamp = new Date();
    
    newMobyData = new Object;
    newMobyData.id = uniqueId();
    newMobyData.title = title;
    newMobyData.link = '';
    newMobyData.description = '';
    newMobyData.geo_latlong = '';
    newMobyData.pubDate = '';
    newMobyData.username = '';
    newMobyData.avatar = '';
    newMobyData.fullImage = image;
    newMobyData.viewImage = newMobyData.fullImage;
    newMobyData.thumbImage = newMobyData.fullImage;
    newMobyData.squareImage = newMobyData.fullImage;
    newMobyData.pausetime = pausetime;
    newMobyData.lastupdate = currentTimeStamp;
    newMobyData.isStatic = true;
    
    mobyStaticConfig[mobyStaticConfig.length] = newMobyData;
}

// add random picture to the stream to entertain the crowd
function mobyRandomContentProvider() {
    randomLength = mobyRandomData.length;
    
    
    //console.log("random content: " + randomLength);
    if (randomLength != 0) {
        currentTimeStamp = new Date();
        if (((currentTimeStamp - mobyLastUpdate) / 1000) > 20 && mobyData.length == 0 && mobyLastUpdate != 0)
        mobyData[mobyData.length] = mobyRandomData[Math.floor(Math.random() * randomLength) ];
    }
}

// checks and add static content to the mobyqueue if required
function mobyStaticContentProvider() {
    //console.log("static image data length:" + mobyData.length);
    if (mobyStaticConfig.length != 0) {
        currentTimeStamp = new Date();
        if (((currentTimeStamp - mobyStaticLastUpdate) / 1000) > mobyStaticMinimalInterval) {
            if (mobyLastStatic == true && mobyStaticConfig.length == 1)
            return false;
            
            if (((currentTimeStamp - mobyStaticLastUpdate) / 1000) > mobyStaticTimeout || mobyLastStatic == false) {
                staticIndex = 0;
                validStatic = false;
                
                $.each(mobyStaticConfig, function (i, item) {
                    
                    if (((currentTimeStamp - mobyStaticConfig[i].lastupdate) / 1000) > mobyStaticConfig[i].pausetime) {
                        if (mobyStaticConfig[i].lastupdate < mobyStaticConfig[staticIndex].lastupdate || i == 0) {
                            staticIndex = i;
                            validStatic = true;
                        }
                    }
                });
                
                if (validStatic) {
                    mobyStaticConfig[staticIndex].lastupdate = currentTimeStamp;
                    mobyStaticLastUpdate = currentTimeStamp;
                    mobyData[mobyData.length] = mobyStaticConfig[staticIndex];
                    return true;
                }
            }
        }
    }
    
    return false;
}

// moby animation
function mobyScroller() {
    // check if static content needs to be provided
    if (mobyStaticContentProvider() !== true)
    mobyRandomContentProvider();
    
    // if there is content present, go scroll
    if (mobyData.length == 0)
    setTimeout('mobyScroller()', 2000); else
    mobyScrollPrepare();
}

// prepare a mobyscroll (preload the image)
function mobyScrollPrepare() {
    try {
        mobyScrollPreIterator = 0;
        mobyScrollPreloader = new Image();
        mobyScrollPreloader.src = mobyData[mobyData.length - 1].viewImage;
    }
    catch (err) {
    }
    setTimeout('mobyScrollPrepareIterate()', 400);
}

// check if the image is loaded in the browser memory (maximum 3 seconds or 10 iterations load time)
function mobyScrollPrepareIterate() {
    mobyScrollPreIterator++;
    
    if (imageLoaded(mobyScrollPreloader) || mobyScrollPreIterator == 10) {
        try {
            mobyScroller_do();
        }
        catch (err) {
        }
        
        if (mobyData.length > 10) {
            setTimeout('mobyScroller()', 7000);
        } else if (mobyData.length > 5) {
            setTimeout('mobyScroller()', 9000);
        } else {
            setTimeout('mobyScroller()', 12000);
        }
    } else {
        setTimeout('mobyScrollPrepareIterate()', 300);
    }
}

function mobyScroller_do() {
    if (mobyPauseIsShown)
    mobyPauseScreen_out();
    
    mobyCurrentMem++;
    
    mobyLastUpdate = new Date();
    
    if (mobyCurrentMem != 0) {
        
        if (mobyCurrentMem >= 4) {
            $("#mobySmall" + (mobyCurrentMem - 3)) .remove();
        }
        
        $("#smallImages .mobysmall:last") .next(".mobysmallspacer") .remove();
        
        squareClass = "wide";
        
        if ($(".mobycontent img") .attr('width') > $(".mobycontent img") .attr('height'))
        squareClass = "tall";
        
        newSmall = $('<div class="mobysmall" id="mobySmall' + mobyCurrentMem + '"><div class="mobysmallwrapper_' + squareClass + '"><img class="' + squareClass + '" src=" ' + mobyMemory + ' " /></div></div><div class="mobysmallspacer"></div>');
        
        newSmall.prependTo("#smallImages");
        
        $("#smallImages .mobysmall") .animate({
            width: "30%"
        },
        1000);
        
        $("#ImagePreloader img") .each(function (i, item) {
            if ($(this) .attr("src") == mobyMemory) {
                $(this) .remove();
            }
        });
    }
    
    
    mobyIDcounter++;
    mobyIDs[mobyIDs.length] = mobyIDcounter;
    
    mobyItem = mobyData[mobyData.length - 1];
    
    if (mobyItem.isStatic)
    mobyLastStatic = true; else
    mobyLastStatic = false;
    
    $(".mobyPointer") .hide();
    
    
    mobyUser = mobyItem.username;
    
    if (mobyUser != '')
    mobyUser = "<span>" + mobyUser + "</span>"; else
    mobyUser = "&nbsp;";
    
    sweetTime = niceTime(mobyItem.pubDate, timeGMT());
    
    if (sweetTime === undefined)
    sweetTime = "";
    
    mobyContent = $('<div class="hidden mobyPointer" id="moby' + mobyIDcounter + '">' +
    '<div class="textInfo"><span class="fancyTime"><input type="hidden" value="' + mobyItem.pubDate + '" /><span>' + sweetTime + '</span>&nbsp;&nbsp;</span>' + mobyUser + '</div>' +
    '<div class="mobyHeader">' +
    '<div class="mobyAvatar">' +
    '<img src="' + mobyItem.avatar + '" />' +
    '</div>' +
    '<div class="mobyTitle">' +
    autoStyle(mobyItem.title) +
    '</div>' +
    '</div>' +
    '<div class="mobycontent">' +
    '<table><tr><td><img src="' + mobyItem.viewImage + '" /></td></tr></table>' +
    '</div>' +
    '</div>');
    
    $mobContent = mobyContent.find(".mobycontent");
    $mobImg = $mobContent.find('img');
    
    mobyWidth = $mobImg.attr('width');
    mobyHeight = $mobImg.attr('height')
    
    if (mobyWidth < mobyHeight) {
        mobReConcider = false;
        $mobImg.addClass('tall');
    } else {
        mobReConcider = true;
        $mobImg.addClass('wide');
    }
    
    mobyContent.prependTo(".mobyBlock");
    mobyData.remove(mobyData.length - 1);
    mobyContent.fadeIn(800);
    
    style_bigImages();
    
    if (mobReConcider) {
        contentHeight = $mobContent.height();
        contentWidth = $mobContent.width();
        
        if (((contentWidth / mobyWidth) * mobyHeight > contentHeight))
        $mobImg.removeClass('wide') .addClass('tall'); else
        $mobImg.removeClass('tall') .addClass('wide');
    }
    
    mobyMemory = mobyItem.viewImage;
    
    if (mobyIDs.length >= 2) {
        $("#moby" + mobyIDs[0]) .remove();
        mobyIDs.remove(0);
    }
}

// function to show the pause screen
function mobyPauseScreen_in() {
    if (! mobyPauseIsShown) {
        $("#pauseScreen") .animate({
            width: "41%"
        },
        1000);
        mobyPauseIsShown = true;
    }
}

// function to hide the pause screen
function mobyPauseScreen_out() {
    if (mobyPauseIsShown) {
        $("#pauseScreen") .animate({
            width: "0%"
        },
        1000);
        mobyPauseIsShown = false;
    }
}

// Time in seconds until messages are shown again (0 = do not reshow messages)
textReshowTime = 300;

// Add all the (tweet)streams needed
//AddTextStream("search", 'hunted OR #hunted OR @hunted OR #H2009', 'geocode=');
AddTextStream("search", 'from:hunted OR @hunted OR #huntednl', 'geocode=');

// Add all the mobystreams needed
AddMobyStream("feed", "http://www.mobypicture.com/json/huntednl/group.json");
