// ==UserScript==
// @name          ULTIMATE Newzbin IMDB Suite
// @description  Cross references each IMDB-linked movie in the page, inserts the ratings (graphical and textual), the description, the genre, right inline with the movie... Additional Features: optional color highlighting, ex: any movie rated greater than 7 mark it green or less than 5 mark it red. Custom HTML injected into Newzbin for a user interface to control the script.  Allows sorting by rating. Remembers all your settings, updates instantly when you change any setting.
// @include       http*://*.newzbin.com/*
// @version       1.0
// ==/UserScript==
var origHTML="";
var maybeHideLoadIndicator;
function getCSSRule(ruleName, deleteFlag) {               // Return requested style obejct
   ruleName=ruleName.toLowerCase();                       // Convert test string to lower case.
   if (document.styleSheets) {                            // If browser can play with stylesheets
      for (var i=0; i<document.styleSheets.length; i++) { // For each stylesheet
         var styleSheet=document.styleSheets[i];          // Get the current Stylesheet
         var ii=0;                                        // Initialize subCounter.
         var cssRule=false;                               // Initialize cssRule. 
         do {                                             // For each rule in stylesheet
            if (styleSheet.cssRules) {                    // Browser uses cssRules?
               cssRule = styleSheet.cssRules[ii];         // Yes --Mozilla Style
            } else {                                      // Browser usses rules?
               cssRule = styleSheet.rules[ii];            // Yes IE style. 
            }                                             // End IE check.
            if (cssRule)  {                               // If we found a rule...
               if (cssRule.selectorText.toLowerCase()==ruleName) { //  match ruleName?
                  if (deleteFlag=='delete') {             // Yes.  Are we deleteing?
                     if (styleSheet.cssRules) {           // Yes, deleting...
                        styleSheet.deleteRule(ii);        // Delete rule, Moz Style
                     } else {                             // Still deleting.
                        styleSheet.removeRule(ii);        // Delete rule IE style.
                     }                                    // End IE check.
                     return true;                         // return true, class deleted.
                  } else {                                // found and not deleting.
                     return cssRule;                      // return the style object.
                  }                                       // End delete Check
               }                                          // End found rule name
            }                                             // end found cssRule
            ii++;                                         // Increment sub-counter
         } while (cssRule);                                // end While loop
      }                                                   // end For loop
   }                                                      // end styleSheet ability check
   return false;                                          // we found NOTHING!
}                                                         // end getCSSRule 

function killCSSRule(ruleName) {                          // Delete a CSS rule   
   return getCSSRule(ruleName,'delete');                  // just call getCSSRule w/delete flag.
}                                                         // end killCSSRule

function addCSSRule(ruleName, cssRule) {                           // Create a new css rule
   if (document.styleSheets) {                            // Can browser do styleSheets?
      if (!getCSSRule(ruleName)) {                        // if rule doesn't exist...
         if (document.styleSheets[0].addRule) {           // Browser is IE?
            document.styleSheets[0].addRule(ruleName, cssRule,0);      // Yes, add IE style
         } else {                                         // Browser is IE?
            document.styleSheets[0].insertRule(ruleName+' {'+ cssRule + '}', 0); // Yes, add Moz style.
         }                                                // End browser check
      }                                                   // End already exist check.
   }                                                      // End browser ability check.
   return getCSSRule(ruleName);                           // return rule we just created.
} 




/*GM_setValue("useColors", true);
GM_setValue("goodMovieThreshold", 7);
GM_setValue("badMovieThreshold", 5);
GM_setValue("removeMoviesLowerThan", 5);
GM_setValue("removeUnrated", true);
*/
GM_setValue("removeUnrated", true);

var useColors = GM_getValue("useColors", false);
var showStars = GM_getValue("showStars", true);
var showRating = GM_getValue("showRating", true);
var showDescription = GM_getValue("showDescription", true);
var showGenre = GM_getValue("showGenre", true);
var sortByRatings = GM_getValue("sortByRatings", false);

var goodMovieThreshold = parseFloat(GM_getValue("goodMovieThreshold", 7));
var badMovieThreshold = parseFloat(GM_getValue("badMovieThreshold", 4));
var removeMoviesLowerThan = parseFloat(GM_getValue("removeMoviesLowerThan", 5));
var removeUnrated = GM_getValue("removeUnrated", false);
var movies = document.evaluate(
   "//tbody[@class='odd' or @class='odd-new' or @class='even' or @class='even-new']",
   document,
   null,
   XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
   null);


var imdbLinkRegex = new RegExp("http://[a-z.]+\.imdb\.com/[a-zA-Z0-9/+_-]+");
var ratingRegex = new RegExp("<b>([0-9]\.[0-9]+)(?=/10)");
var descRegex = new RegExp("<h5>Plot:[^<>]*</h5>([^]*?)(?=<a class)");
var genreRegex = new RegExp("<h5>Genre:[^<>]*</h5>([^]*?)(?=<a class)");
var newzBinTitleRegex = new RegExp("^http[s]*:\/\/(v3|www)\.newzbin\.com\/browse\/post\/[0-9]+\/$");
var newzBinGroupRegex = new RegExp("<span style=");


	
//setupMoviesDisplay();
		/*try{document.getElementById("loadIndicator").style.display = "";}
		catch(e){}*/
var movieRatingArray = new Array();

for (var i = 0; i < movies.snapshotLength; i++)
{
	var entireRow = movies.snapshotItem(i);
	entireRow.id="movie" + i;
	
	var imdbLink = entireRow.innerHTML.match(imdbLinkRegex);
	
	if (imdbLink) 
		getRating(entireRow, imdbLink.toString());
}
/*try{document.getElementById("loadIndicator").style.display = "none";		
}catch(e){}
*/

function getRating(entireRow, imdbLink)
{
/*var storedMovieInformation = GM_getValue(imdbLink, '');
if(storedMovieInformation != '')
	return storedMovieInformation;
*/
	
	//else:
   GM_xmlhttpRequest({
      method: 'GET',
      url: imdbLink,
	  headers: {'Referer': imdbLink, 'Accept': 'application/atom+xml,application/xml,text/xml', 'User-agent': 'Mozilla/4.0 (compatible)', 'overrideMimeType': 'text/html; charset=ISO-8859-1'},
      onload: function (responseDetails)
      {
	  clearTimeout(maybeHideLoadIndicator);
		try{document.getElementById('loadIndicator').style.display='';}catch(e){}
		
		var futureStorage = "";
         if (responseDetails.status == 200)
         {
            var ratingMatch = responseDetails.responseText.match(ratingRegex);
			var descMatch = responseDetails.responseText.match(descRegex);
			var genreMatch = responseDetails.responseText.match(genreRegex);
			
			if (descMatch)
				description = descMatch[1].replace("href=\"/", "href=\"http://www.imdb.com/");
            if (ratingMatch)
            {
            	rating = parseFloat(ratingMatch[1]);
				movieRatingArray.push(rating.toString() + ' ' + entireRow.id);
				entireRow.className+=" rating" + parseInt(rating).toString();
			
				var ratingWithStarHTML = "<div class=\"IMDBstars\">"
				 + "<div class=\"IMDBstarsCHILD\" style=\"width:" + ((rating/10*200)).toString() + "px;\"></div></div>"+
				 "<span class=\"IMDBrating\" style=\"font-weight:bold;position:relative;top:-20px;left:220px;" /*+ (rating>=goodMovieThreshold ? "color:white;":"") */ + "\">" + rating + "/10</span>";
				//curLink.parentNode.parentNode.innerHTML+= ratingWithStarHTML;
				entireRow.childNodes[1].childNodes[7].innerHTML+= ratingWithStarHTML;
				futureStorage += ratingWithStarHTML;
						
            }
            
            
			if (descMatch)
            {
                //add description for different layout
                //ugly but does the job
                var description = descMatch[1].replace("href=\"/", "href=\"http://www.imdb.com/");
				if(description.substring(description.length -2,description.length).indexOf('|') != -1)
					description = description.substring(0, description.length - 2);

						var descriptionHTML = "<span class=\"IMDBdescription\" style=\"font-weight:bold;" /*+ (rating>=goodMovieThreshold ? "color:white;":"") */+ "position:relative;top:-5px;\"><br/>" + description + "</span>";
						
						var genreHTML = "";
						if(genreMatch)
						{
							genreHTML += "<span class=\"IMDBgenre\"><br/>" + genreMatch[0].replace(/(<([^>]+)>)/ig,"").substring(7) +"</span>";
							if(genreHTML.indexOf("Tagline:") != -1)
							{
								genreHTML = genreHTML.substring(0, genreHTML.indexOf("Tagline:"));
							}
						}
						entireRow.childNodes[1].childNodes[7].innerHTML += descriptionHTML + genreHTML;

						futureStorage+= descriptionHTML;
						//curLink.innerHTML += "<span>" + description + "</span>";
		    }
            	
            
			
//			GM_setValue(imdbLink, futureStorage);
         }
     	  maybeHideLoadIndicator = window.setTimeout(function(){try{document.getElementById('loadIndicator').style.display='none';
		  sortNow();
		  }catch(e){}}, 2000);
	  }
   });
}

function $$(xpath,root) { 
  xpath=xpath.replace(/((^|\|)\s*)([^/|\s]+)/g,'$2.//$3').
             replace(/\.([\w-]+)(?!([^\]]*]))/g,'[@class="$1" or @class$=" $1" or @class^="$1 " or @class~=" $1 "]').
              replace(/#([\w-]+)/g,'[@id="$1"]').
              replace(/\/\[/g,'/*[');
  str='(@\\w+|"[^"]*"|\'[^\']*\')'
  xpath=xpath.replace(new RegExp(str+'\\s*~=\\s*'+str,'g'),'contains($1,$2)').
              replace(new RegExp(str+'\\s*\\^=\\s*'+str,'g'),'starts-with($1,$2)').
              replace(new RegExp(str+'\\s*\\$=\\s*'+str,'g'),'substring($1,string-length($1)-string-length($2)+1)=$2');
  var got=document.evaluate(xpath,root||document,null,null,null), result=[];
  while(next=got.iterateNext()) result.push(next);
  return result;
}

window.addEventListener("load", function(e) {
$$(".selection")[0].lastChild.innerHTML+=
	"<li>Minimum Rating: <input id=\"removeMoviesLowerThan\" type=\"textbox\" maxlength=\"1\" size=\"1\" value=\"" + removeMoviesLowerThan + "\"/></li>"+
	"<li><label for=\"useColors\">Colors: </label><input id=\"useColors\" type=\"checkbox\" " + (useColors ? "checked=\"true\"":"") + "/></li>"+
	"<li id=\"goodMovieThresholdLI\" >Good Rating: <input id=\"goodMovieThreshold\"  type=\"textbox\" maxlength=\"1\" size=\"1\" value=\"" + goodMovieThreshold + "\"/></li>" + 
	"<li id=\"badMovieThresholdLI\">Bad Rating: <input id=\"badMovieThreshold\" type=\"textbox\" maxlength=\"1\" size=\"1\" value=\"" + badMovieThreshold + "\"/></li>" +
	"<li><label for=\"showStars\">Stars: </label><input id=\"showStars\" type=\"checkbox\" " + (showStars ? "checked=\"true\"":"") + "/></li>"+
	"<li><label for=\"showRating\">Rating: </label><input id=\"showRating\" type=\"checkbox\" " + (showRating ? "checked=\"true\"":"") + "/></li>"+
	"<li><label for=\"showDescription\">Description: </label><input id=\"showDescription\" type=\"checkbox\" " + (showDescription ? "checked=\"true\"":"") + "/></li>"+
	"<li><label for=\"showGenre\">Genre: </label><input id=\"showGenre\" type=\"checkbox\" " + (showGenre ? "checked=\"true\"":"") + "/></li>" +
	"<li><label for=\"sortByRatings\">Sort by Rating: </label><input id=\"sortByRatings\" type=\"checkbox\" " + (sortByRatings ? "checked=\"true\"":"") + "/></li>"

	+
	"<li><img id=\"loadIndicator\" src=\"data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==\"/></li>";
	
	document.getElementById("useColors").addEventListener("click", refreshRatings, false);
	document.getElementById("showStars").addEventListener("click", refreshRatings, false);
	document.getElementById("showRating").addEventListener("click", refreshRatings, false);
	document.getElementById("showDescription").addEventListener("click", refreshRatings, false);
	document.getElementById("showGenre").addEventListener("click", refreshRatings, false);
	document.getElementById("sortByRatings").addEventListener("click", refreshRatings, false);

	document.getElementById("removeMoviesLowerThan").addEventListener("keyup", refreshRatings, false);
	document.getElementById("goodMovieThreshold").addEventListener("keyup", refreshRatings, false);
	document.getElementById("badMovieThreshold").addEventListener("keyup", refreshRatings, false);
	
	document.getElementById("goodMovieThresholdLI").style.display = document.getElementById("badMovieThresholdLI").style.display =  useColors ? "":"none";
	setupMoviesDisplay();
//	document.getElementById("loadIndicator").style.display = "none";
},false);


var starsPNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAqCAYAAAD21BQXAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABJRJREFUeNrs3E+IG1UcB/A3k5nJv/2bNDa7WFZpi9CDXUqloAcRrYjiqYsggpe2oAcvvfWgLBYKHnry4KWnXvQQka6eKgqrIFoXtZdid4tmac3udps/m+xMMn+ScX6zzjbJzmaGJh5e+P5gNi87bz7zCPx4M+/NG8G2bYZAIPxDDFvRtlvyIE8MDx4PnhgWW1/feHGQjYMHjwcvVIKoqjZtGMZ4o9HIDKKB8ODx4olhsq1Wqx11ijlN06YHkb3w4PHiBSaIrhsTTrZ9S2UHPtLvtSA8eDx5YlC2dWVZrlyuHOsne+HB48mTvAMps6hsWVbCybAJr4KTZX+0H0BZ1/49kUgUvHIsFtuEB2+YPIHmQQikTPqvcu4xknNudHT0biqVuuU1EB68YfCE9onCUql0/DHQuXQ6vTQyMrLavQMePN49oXsmfXt7e6ZYLJ4Mic5NTU1/pyhyZb8K8ODx7Al+j5oYhjmxtlZ4uReqKMrpbPbgoiCIZtBZ4cHj1RP9K8sV54CtXieNRqObYRoHDx7PnrjfcBjNNPYeT9ZDz2rCg8erJ/pXdofFcr27rd4nhAdvGDzfBOmaTKEhr1nn5mWSPum7tyPsszHw4PHqSX7dkQfRdVsm88RPkhTR6B+pVKpCEynlcvk0ZRxNwoTp3uDB49bbmSjs3AqFwiv1ej3jt8/barUaDZ8d71UHHjzePQErChGI/UPET4BAIEEQiP83QeymOjPIE8ODx4MnhsX0zYv5QTYOHjwevFAJUq98nzP1NWZoK2cH8XYJePB48UKNYpWWX7flaJKx6KtsNHte6LeB8ODx4gX2IFrx618bqsFMXWVMv9H3tSA8eDx5gQmyXVw82d099dNAePB48naW3DpZVC2tvBtPJgtW/c/3mua6i9Srd5hW/oUpSpTFkgozrTEmSE+y+NgzLCJnl6iO2Tq0QMdRWY4fvkaPDMODNzSelyB/3fo4//D+ops14+Ox3QyKxZou6JYd1EUcuD1kqcpi6feXEuk3n/NGCeDB49xjjrdziSVEkquHT3wijE29xTY2Tba11XA3ikYjwgxD3yk71260dUdk8vJH8dQbz3sjAvDgDYGnOJ7SMYpFJ/jn7le3f/vhsvsqlIMZeTf7KPMovOxzoegBNvnUpXNe17ZnvBkePM69yPz8/KMbEkFojaWPfZo9dKq1emfhJVVrMSliO5jELEtkkmQzVaXliU45OcvSRz5LytEDN+k43xscePA493xHscYzs5fiyad3v7d3TxTVquXe2HjP1QcFPHi8er4JQiur6urfbpmu4TzUgynu36uFHlqDB49Xb++KwqY6s7HxsGOs2EM7spItOH8vBDYOHjyevT09CI0AaA++7Jg8OfrsO+y1t784l8q+0JGBoZ5lgQePZ697iaFpWokfv/nAvn71hE2furp8ttVqyrSPPisPfv/wxudn7J+vn7LvLedWgpY7woPHs+eL0gH5fP4MvS6lex+htBF2++YVO8yaYHjwePV8n+bdnXAJ+ea6wOtAePA49fDSBgSiR2BNOgIxiAShN2QP8sTw4PHg/SvAAHpxTwCU0Qw2AAAAAElFTkSuQmCC";
function setupMoviesDisplay()
{
clearTimeout(maybeHideLoadIndicator);
	if(useColors)
				{
					killCSSRule("div#content table.dataTabular tbody.even tr td");
					killCSSRule("div#content table.dataTabular tbody.even tr td");
					killCSSRule("div#content table.dataTabular tbody tr td");
					killCSSRule("div#content table.dataTabular tbody tr td");
					killCSSRule("div#content table.dataTabular tbody.odd tr td");
					killCSSRule("div#content table.dataTabular tbody.odd tr td");
					killCSSRule("div#content table.dataTabular tbody.odd-new tr td"); 
					killCSSRule("div#content table.dataTabular tbody.odd-new tr td"); 
					killCSSRule("div#content table.dataTabular tbody.even-new tr td");
					killCSSRule("div#content table.dataTabular tbody.even-new tr td");
				}
killCSSRule(".IMDBstars");
killCSSRule(".IMDBstarsCHILD");
killCSSRule(".IMDBrating");
killCSSRule(".IMDBdescription");
killCSSRule(".IMDBgenre");

if(!showStars)
{
	addCSSRule(".IMDBstars", "display:none");
}
else
{
	addCSSRule(".IMDBstars", "text-align:right;width:200px;height:20px;background:transparent url("+starsPNG+") no-repeat scroll 0 0;");
	addCSSRule(".IMDBstarsCHILD", "height:20px;background:transparent url("+starsPNG +") no-repeat scroll 0 -20px;");
}
if(!showRating)
	addCSSRule(".IMDBrating", "display:none");
if(!showDescription)
	addCSSRule(".IMDBdescription", "display:none");
if(!showGenre)
	addCSSRule(".IMDBgenre", "display:none");

	for(var r=0;r<10;r++)
		{
			//rating0..rating5
			var rClass = "rating" + r.toString();
			killCSSRule("." + rClass);
			if(r < removeMoviesLowerThan)
				addCSSRule("." + rClass, "display:none;");
			else
			{
				if(useColors)
				{
					if(r >= goodMovieThreshold)
						addCSSRule("." + rClass, "background-color:#DFFFE3;");
					else if(r < badMovieThreshold)
						addCSSRule("." + rClass, "background-color:#FFCFCF;");
					
				}
			}
		}

		
		
		

		try{
		document.getElementById("loadIndicator").style.display = "none";
		}catch(f){}
}

function refreshRatings()
{
	document.getElementById("loadIndicator").style.display = "";
	useColors = document.getElementById("useColors").checked;
	showStars = document.getElementById("showStars").checked;
	showRating = document.getElementById("showRating").checked;
	showDescription = document.getElementById("showDescription").checked;
	showGenre = document.getElementById("showGenre").checked;
	var oldSort = sortByRatings;
	sortByRatings = document.getElementById("sortByRatings").checked;
	
	if(document.getElementById("removeMoviesLowerThan").value.length > 0)
		removeMoviesLowerThan = parseFloat(document.getElementById("removeMoviesLowerThan").value);
	if(document.getElementById("goodMovieThreshold").value.length > 0)
		goodMovieThreshold = parseFloat(document.getElementById("goodMovieThreshold").value);
	if(document.getElementById("badMovieThreshold").value.length > 0)
		badMovieThreshold = parseFloat(document.getElementById("badMovieThreshold").value);
	
	document.getElementById("goodMovieThresholdLI").style.display = document.getElementById("badMovieThresholdLI").style.display =  useColors ? "":"none";

	GM_setValue("useColors", useColors);
	GM_setValue("showStars", showStars);
	GM_setValue("showRating", showRating);
	GM_setValue("showDescription",showDescription);
	GM_setValue("showGenre",showGenre);
	GM_setValue("sortByRatings", sortByRatings);
	
	GM_setValue("removeMoviesLowerThan", removeMoviesLowerThan);
	GM_setValue("goodMovieThreshold", goodMovieThreshold);
	GM_setValue("badMovieThreshold", badMovieThreshold);
	setupMoviesDisplay();
	if(oldSort!=sortByRatings)
		sortNow();
}


function sortNow()
{
		//Sorting

if(sortByRatings)
{

		var theadHTML = $$('.dataTabular')[0].childNodes[1].innerHTML;
		var movieHTML = theadHTML;
		origHTML = $$('.dataTabular')[0].innerHTML;
		movieRatingArray.sort(function(a,b) {
			var pA = parseFloat(a.split(' ')[0]);
			var pB = parseFloat(b.split(' ')[0]);
			return pB-pA;
		});
		for(var i=0;i<movieRatingArray.length;i++)
		{
			var movieID = movieRatingArray[i].split(' ')[1];
			movieHTML += "<tbody class=\"" + document.getElementById(movieID).className + "\">" + document.getElementById(movieID).innerHTML + "</tbody>";
		}
		
		$$('.dataTabular')[0].innerHTML = movieHTML;
		setupMoviesDisplay();
}
else if(origHTML.length > 0)
{
	$$('.dataTabular')[0].innerHTML = origHTML;
	origHTML = '';
}
		////End sorting
}