// ==UserScript==
// @name          Prefetch Flickr Photostream
// @version       1.0
// @description	  Prefetch the prev/next photos of current Flickr photostream to speed up browsing
// @namespace     http://webdev.yuan.cc/
// @include       http://flickr.com/photos/*
// @include       http://www.flickr.com/photos/*

// v1.0	01/17/06	initial release
//
// Author: .CK ( http://www.flickr.com/photos/ckyuan/ )
// Web site: http://webdev.yuan.cc/
//           http://flickr.tw/
//
// ==/UserScript==

(function() {

INDICATOR = true;
MAX_BUFFER = new Array();
MAX_BUFFER['prev'] = 3;
MAX_BUFFER['next'] = 3;

var re = /http:\/\/(www\.)?flickr\.com\/photos\/[^\/]+\/\d+/;
if( ! re.test(document.location) ) return;

if(unsafeWindow) w = unsafeWindow;
else w = window;
var global_photos = w.global_photos;

function _gt(e) { return document.getElementsByTagName(e); }
function _gi(e) { return document.getElementById(e); }
function _ce(e) { return document.createElement(e); }
function _ct(e) { return document.createTextNode(e); }

var h = _gt('h3');
var prefetch = new Array();
if( h.length == 0 ) return;
for(var i=0;i<h.length;i++) {
    if( h[i].className == 'contextTitleOpen' ) {
	var h3 = h[i];
	break;
    }
}
var api_method = 'flickr.photos.getContext';
if( h3.innerHTML.match(/(Pool)/) ) {
    var group_id = h3.id.replace(/contextTitle_pool/,'');
    api_method = 'flickr.groups.pools.getContext&group_id=' + group_id;
}
if( h3.innerHTML.match(/(Set)/) ) {
    var set_id = h3.id.replace(/contextTitle_set/,'');
    api_method = 'flickr.photosets.getContext&photoset_id=' + set_id;
}

var prefetchDiv = _ce('div');
prefetchDiv.style.display = 'none';
prefetchDiv.innerHTML = '';
document.body.appendChild(prefetchDiv);

var bubble_div = _ce('div');
bubble_div.style.display = (INDICATOR) ? 'block' : 'none';
bubble_div.style.width = '238px';
bubble_div.style.backgroundColor = '#f3f3f3';
bubble_div.style.borderStyle = 'solid';
bubble_div.style.borderColor = '#e3e3e3';
bubble_div.style.borderWidth = '0px 1px 1px 1px';
bubble_div.style.lineHeight = '10px';
bubble_div.style.paddingTop = '1px';
bubble_div.style.textAlign = 'center';
var bubble = _ce('span');
bubble.style.color = 'blue';
bubble.style.fontSize = '9px';
bubble.innerHTML = '|';
bubble_div.appendChild(bubble);

var streamImg = h3.parentNode.parentNode.nextSibling.nextSibling.getElementsByTagName('img');
var streamDiv = h3.parentNode.parentNode.parentNode.parentNode.parentNode;
streamDiv.appendChild(bubble_div);
var order = 'prev';
for(i=0;i<streamImg.length;i++) {
    if( streamImg[i].src.match(/static.flickr.com/) ) {
	var tmp = new Object();
	tmp.src = streamImg[i].src;
	tmp.dir = order;
	tmp.done = false;
	prefetch.push(tmp);
	order = 'next';
    }
}
for (var x in w.global_photos) {
    if( _gi('photoImgDiv'+x) ) photo_id = global_photos[x].id;
    else return;
}
var currentImg = _gi('photoImgDiv'+x).firstChild;

var imgOnLoadHandler = function() {
    for(i in prefetch) {
	if( prefetch[i].done ) continue;
	var dir = prefetch[i].dir;
	var str = prefetch[i].src.replace(/_s\.jpg/, '.jpg');
	str += '?v=0';
	var re = /static.flickr.com\/(\d+)\/(\d+)_(\w+)\.jpg/;
	var a = re.exec(str);
	var photo_id = a[2];
	var secret = a[3];
	var rel = 'bubble_' + photo_id;
	prefetchDiv.innerHTML += '<img src="' +prefetch[i].src+ '" />';
	prefetchDiv.innerHTML += '<img photoid="' +photo_id+ '" dir="' +dir+ '" rel="' +rel+ '" src="' +str+ '" onLoad="img_loaded(this)" />';

	var bubble = _ce('span');
	bubble.id = rel;
	bubble.style.color = 'red';
	bubble.style.fontSize = '9px';
	bubble.innerHTML = '|';
	if( dir == 'prev' ) {
	    if( bubble_div.firstChild ) bubble_div.insertBefore(bubble,bubble_div.firstChild);
	    else bubble_div.appendChild(bubble);
	}
	if( dir == 'next' ) bubble_div.appendChild(bubble);
	prefetch[i].done = true;
    }
}

if( currentImg.complete ) {
    w.prefetch = imgOnLoadHandler;
    w.setTimeout('prefetch()', 1000);
} else currentImg.addEventListener('load', imgOnLoadHandler, true);

w.img_loaded = function(x) {
    var id = x.getAttribute('rel');
    var dir = x.getAttribute('dir');
    var photo_id = x.getAttribute('photoid');
    _gi(id).style.color = '#00ff00';

    var url =  'http://www.flickr.com/services/rest/?method=' + api_method;
    url += '&api_key=bc60075f4ce963fab3fac473d0741fe8';
    url += '&photo_id=' + photo_id;
    var headers = { 'User-agent': 'Mozilla/4.0 (compatible) Greasemonkey/Prefetch Flickr Photostream', 'Accept': 'application/atom+xml,application/xml,text/xml', 'X-photo': id };
    GM_xmlhttpRequest({
	method: 'GET', url: url, headers: headers,
	onload: function(responseDetails) {
	    var parser = new w.DOMParser();
	    var dom = parser.parseFromString(responseDetails.responseText, "application/xml");
	    var stat = dom.getElementsByTagName('rsp')[0].getAttribute('stat');
	    if( stat == 'ok' ) {
		var dir = '',count=0;
		var prev_id = dom.getElementsByTagName('prevphoto')[0].getAttribute('id');
		var next_id = dom.getElementsByTagName('nextphoto')[0].getAttribute('id');
		if( prev_id != undefined && !_gi('bubble_' + prev_id) ) {
		    var dir = 'prev';
		    var tag = dom.getElementsByTagName('prevphoto')[0];
		    var photo_id = prev_id;
		}
		if( next_id != undefined && !_gi('bubble_' + next_id) ) {
		    var dir = 'next';
		    var tag = dom.getElementsByTagName('nextphoto')[0];
		    var photo_id = next_id;
		}
		if( dir == '' || !tag ) return;
		var secret = tag.getAttribute('secret');
		var thumb = tag.getAttribute('thumb');
		if( !thumb ) return;
		var tmp = new Object();
//		tmp.src = thumb.replace(/_s\.jpg/, '.jpg');
		tmp.src = thumb;
		tmp.dir = dir;
		tmp.done = false;
		for(var i in prefetch) if( prefetch[i].dir == dir ) count++;
		if( count >= MAX_BUFFER[dir] ) return;
		prefetch.push(tmp);
		imgOnLoadHandler();
	    }
	}
    });
}

})();
