// ==UserScript==
// @name           YouTube Highest
// @version        1.2
// @namespace      reniris
// @description    Always watching or downloading the highest quality format (HD or MP4 or fmt=35) in YouTube Page
// @include        http://*.youtube.com/*
// @include        http://youtube.com/*
// ==/UserScript==
/*
YouTube HD Suite改造版 fmt35に対応
元URL　http://creazy.net/2008/12/youtube_hd_suite_greasemonkey.html
*/
(function() {

	var d = document;
	var w = (typeof(unsafeWindow) != 'undefined') ? unsafeWindow : window;
	var l = location;
	var s = w.swfArgs;
	//各フォーマットごとのパラメータ
	var format_params = [
							['&fmt=22','22/2000000/9/0/115','#f00','HD',22,'.mp4'],
							['&fmt=35','35/640000/9/0/115','#00f','fmt35',35,'.flv']
						];

	/**
	 * Controller
	 */
	if ( l.host.match(/[a-zA-Z\.]*youtube\.com$/) ) {
		// Watching Page
		if ( l.pathname.match(/\/watch/) ) {
			// always watch in Highest Quality
			if ( !l.search.match(/fmt=[0-9]*/) ) {
				redirect();
			} else {
				showDownloadLinks();
			}
		}
		// Other Page (Top, Browse, seache, ...)
		else {
			// for Auto Pager
			var scrollHeight = d.documentElement.scrollHeight;
			d.addEventListener(
				"scroll",
				function(e){
					if(d.documentElement.scrollHeight - scrollHeight > 100){
						scrollHeight = d.documentElement.scrollHeight;
						visualize();
					}
				},
				false
			);
		}
		// execute "visualize" all pages
		visualize();
	}
	
	/**
	 * Redirect Higher Quality URL
	 */
	function redirect() {
		for ( var i=0; i<format_params.length; i++ ) {
			if ( s['fmt_map'].indexOf(format_params[i][1]) > -1 ) {
				l.replace(l.href + format_params[i][0]);
				return;
			}
		}
		l.replace(l.href + '&fmt=18');
	}
	
	/**
	 * create XmlHttpRequest
	 */
	function createXHR() {
		if ( w.ActiveXObject ) {
			try {
				return new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					return new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e2) {
					return null;
				}
			}
		} else if ( w.XMLHttpRequest ) {
			return new XMLHttpRequest();
		} else {
			return null;
		}
	}

	/**
	 * check URL
	 */
	function checkURL(video_id) {
		var url
			= 'http://'+location.host+'/watch'
			+ '?v='+video_id;
		var XHR = createXHR();
		XHR.open( 'GET', url, true );
		XHR.onreadystatechange = function() { 
			if (XHR.readyState==4) {
				if ( match = XHR.responseText.match(/var swfArgs = ({.*})/) ) {
					json = eval('('+RegExp.$1+')');
					var s = d.getElementsByTagName('strong');
					for ( var i=0; i<s.length; i++ ) {
						if ( !s[i].innerHTML && s[i].getAttribute('class') == json['video_id'] ) {
							link = d.createElement('a');
							link.style.color   = '#fff';
							link.style.font    = 'bold 10px/10px Arial';
							link.style.padding = '1px';

							//default link
							link.style.backgroundColor = '#666';
							link.href      = '/get_video?fmt=18&video_id='+json['video_id']+'&t='+json['t'];
							link.innerHTML = 'MP4';
							var next_href = "&fmt=18";

							for ( var j=0; j<format_params.length; j++ ) {
								if ( json['fmt_map'].indexOf(format_params[j][1]) > -1 ) {
									link.style.backgroundColor = format_params[j][2];
									link.href      = '/get_video?'+format_params[j][0]+'&video_id='+json['video_id']+'&t='+json['t'];
									link.innerHTML = format_params[j][3];
									next_href = format_params[j][0];
									break;
								}
							}
							s[i].nextSibling.href += next_href;
							s[i].appendChild(link);
						}
					}
				}
			}
		}
		XHR.send('');
	}

	/**
	* Add HD or MP4 on each links in YouTube List Page
	*/
	function visualize() {
		var a = d.getElementsByTagName('a');
		var a_text = '';
		for ( var i=0; i<a.length; i++ ) {
			match = '';
			if ( a[i].innerHTML.indexOf('<img') > -1 )       continue; // Skip Image Link
			if ( a[i].getAttribute('vid') )                  continue; // Skip checked Link
			if ( a[i].getAttribute('class') == 'yt-button' ) continue; // Skip Button Link
			if ( a[i].href.match(/#$/) )                     continue; // Skip functional Link
			
			if ( a[i].href.match(/watch\?v=([a-zA-Z0-9_-]*)/) ) {
				match = RegExp.$1;
				a[i].setAttribute('vid',1);
				strong = d.createElement('strong');
				strong.setAttribute('class',match);
				a[i].parentNode.insertBefore(strong, a[i]);
			}
		}
		
		var s = d.getElementsByTagName('strong');
		
		var c = '';
		for ( var i=0; i<s.length; i++ ) {
			if ( !s[i].innerHTML && s[i].getAttribute('class') && c.indexOf(s[i].getAttribute('class')) < 0 ) {
				c += ' ' + s[i].getAttribute('class');
				checkURL( s[i].getAttribute('class') );
			}
		}
	}
	
	/**
	 * Add HD or MP4 Download Links
	 */
	function showDownloadLinks() {
		var h1s = d.getElementsByTagName('h1');
		if ( h1s.length > 0 && h1s[0].innerHTML ) {
			if ( matches = h1s[0].innerHTML.toLowerCase().match(/([0-9a-z_-]+)/g) ) {
				file_name_base = matches.join('_');
			} else {
				file_name_base = s['video_id'];
			}
		}
		//alert(file_name_base);
		
		var base_url  = '/get_video?video_id='+s['video_id']+'&t='+s['t']+'&fmt=';
		var base_css  = ' style="padding:10px;font:bold 14px/1.5 Arial"';
		var input_css = ' style="width:200px;font-size:10px;"';
		var html
			= '<div id="watche-downlaod-div">'
			+ '<div id="watche-downlaod-formats-18"'+base_css+'>'
			+ '<a href="'+base_url+'18">[OK] Download MP4(iPod, fmt=18)</a></div>';
		
		for ( var i=0; i<format_params.length; i++ ) {
			if ( s['fmt_map'].indexOf(format_params[i][1]) > -1 ) {
				html
				+= '<div id="watche-downlaod-formats-'+format_params[i][4]+'"'+base_css+'>'
				+  '<a href="'+base_url+format_params[i][4]+'">[OK] Download('+format_params[i][3]+', fmt='+format_params[i][4]+')</a></div>';
			}
			else{
				html += '<div id="watche-downlaod-formats-'+format_params[i][4]+'"'+base_css+'>[NG] Download('+format_params[i][3]+', fmt='+format_params[i][4]+')</div>';
			}
		}
		html += '</div>';
		// Create Links Block
		d.getElementById('watch-video-details-inner').innerHTML += html;
	}
})();