// The Movie Dude
// Version 1.5
// 4 Dec 2005
// Copyright (c) 2005, Adam Vandenberg
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
//
// adapted for Ann Arbor District Library by Edward Vielmetti,
// emv@superpatron.com, http://www.superpatron.com without whom it could not be
// adapted for Farmington Community Library by Kevin Yezbick
// kevin@yezbick.com, http://www.yezbick.com	
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
//
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "The Movie Dude", and click Uninstall.
//
// ==UserScript==
// @name The Movie Dude
// @namespace	http://www.superpatron.com/
// @description 	Cross-links various movie sites
// @include	http://imdb.com/title/*
// @include	http://*.imdb.com/title/*
// @include	http://netflix.com/MovieDisplay?*
// @include	http://www.netflix.com/MovieDisplay?*
// @include	http://blockbuster.com/*
// @include	http://www.blockbuster.com/*
// @include	http://movies.yahoo.com/*
// @include	http://www.rottentomatoes.com/m/*
// @include	http://rogerebert.suntimes.com/*
// @include	http://amazon.com/*
// @include	http://*.amazon.com/*
// @include http://*.farmlib.org/*
// @include http://*.aadl.org/*
// ==/UserScript==

(function(){
	var logo = "data:image/gif;base64,R0lGODlhEAAQALMAAP%2F%2F%2F5q6u46goT9LTOfu7svU1HGCgqnBu7bKy6Gtp1pqaQAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAQABAAAARMMMhJqz0oHysRAWBIFNYXngBJmWhorO1pvNJXzAcqDNNxKINg4bSrCAQJwTBUlBxYrWYAGuUFljFQEzrSWVGGAbQJHmABzaM6qF4HIgA7"
	
	var noFavicon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8%2F9hAAAABGdBTUEAAK%2FINwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHiSURBVHjaYvz%2F%2Fz8DJQAggFhgjOrFNwmY9D%2BqNVZjObooQAAxgFwAwpVzL%2F%2F%2F8%2Bc%2FCv7x4%2Ff%2F58%2Ff%2Fn%2F55e%2F%2FhsXX%2Fqe2bAwA6mGG6QFhgABighn0788fBpBvmJggGOScn3%2F%2BMbz59J2Bg42JIchBgUFSWnF9TvfueEZGRmaYPoAAQjLgN8PfvwwMjIxQASD9D0j9hXpMToyTISNYk4GTi38ukMsLNASsFyCA4GHw%2F%2FdvBqAjGNjYILb%2F%2Bw8xn4WVleH4qesMT56%2FYeD99wOojhskwQfEX0HKAAIIYQBQN8gFIBtBmoGuZ%2FjPxMzAxcPLICwGVMbBxyDN%2Fp%2Fh1ON7IOVwLwAEENyAf78hXvj1F2HA73%2BMDMzsnAy8gpwMTECLpTlB6m6iRAJAACG5AOKF%2F38QBoAM%2Bwnk%2FwBhIBsi%2FxvFAIAAYkGOBZALfv5GcsFfiObvUENA8iB1yAAggFACEaTgyy%2BIAX9hBkAN%2BQo0%2BC8bRB0yAAggDBd8%2FgmJBZgLfkIN%2BAYygAPTBQABhOKCf0BNn6BhAIqN39BAhXkDJI%2FuAoAAYkFOSKCUqMQISUQMKJEFS%2FYQdcgAIIBQ0kFn91yScyNAADHCsjMwaYIMA%2FqSgR2I2QjoAwXEe6DePwABBgAwtxLgQdJKdAAAAABJRU5ErkJggg%3D%3D"

	String.prototype.trim = function() {
		var s = this.replace(/^\s*(.*)/m, "$1");
		s = s.replace(/(.*?)\s*$/m, "$1");
		return s; };
	
	String.prototype.template = function(vars){
		return this.replace( 
			/\{(\w*)\}/g,
			function(match,submatch,index){return vars[submatch];}
		) };

	String.prototype.endsWith = function(suffix){
		var lastIndex = this.lastIndexOf(suffix);
		return (0 <= lastIndex) && (lastIndex == (this.length-suffix.length));
	}
	
	String.prototype.removeSuffix = function(suffix){
		if (this.endsWith(suffix))
			return this.substring(0, this.length-suffix.length);
		else 
			return this;
	}
	
	function foreach(stuff, f){ for(var i=0; i < stuff.length; i++) {
		var stop_iter = f(stuff[i]);if (stop_iter) return;} }

	function foreach_dict(stuff, f){ for(var name in stuff){
		var stop_iter = f(name, stuff[name]);if (stop_iter) return;} }

	function selectNodes(xpath, elem){
		var results = document.evaluate(
			xpath, elem || document, null,
			XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null)
	
		var nodes = new Array();var result = null;
		while(result = results.iterateNext()) nodes.push(result);
		return nodes;
	}
	
	function addCSS(){
		foreach(arguments, GM_addStyle);
	}

	function HidePreferences(){
		var prefs = document.getElementById("_md_prefs"); 
		if(prefs) prefs.style.display="none";		
	}

	function setPreference(event){GM_setValue(this.value, this.checked);}

	function ShowPreferences(){	
		var prefs = document.getElementById("_md_prefs");
		if(!prefs){
			addCSS(
				"#_md_prefs {position:fixed; left:0; right:0; bottom:0; top:auto; width:100%;  color:black; font: normal 11px sans-serif;}",
				"#_md_prefs div {text-align:center; padding:5px 0 0.4em 0; border-top:1px #aaf solid; background:#eee;}",
				"#_md_prefs button {font: normal 11px sans-serif; border: 1px solid #0080cc; color: #333; cursor: pointer; background: #FFF;}",
				"#_md_prefs button[disabled]{background: #CCC;}"
			);
			
			var prefs = document.createElement("div")
			prefs.id = "_md_prefs";
			
			var s = "<div><b>The Movie Dude</b>";
			s += ' <a href="http://adamv.com/dev/grease/" title="Get more Grease at AdamV.Com"><sub><img src="' + logo + '" width="16" height="16" border="0" /></sub></a> ';
			s += "Link to: ";
			
			foreach(movieSiteIDs, function(siteID){
				var siteName = siteNames[siteID];
				var checked = (GM_getValue(siteID, true)) ? " checked='checked'" : "";
				
				s += " &nbsp;<input type='checkbox' name='_md_pref' value='{siteID}'{checked}> {siteName}".template({
					siteID: siteID, checked: checked, siteName: siteName
				});
			})
			
			s += " &nbsp;<button id='_md_close'>Close</button>"
			
			var checked = (GM_getValue("_icons", true)) ? " checked='checked'" : "";
			s += "<br><input type='checkbox' name='_md_pref' value='_icons'{checked}> Icons".template({checked:checked})
			
			s += "</div>"
			prefs.innerHTML = s;
			document.body.appendChild(prefs);
			
			document.getElementById("_md_close").addEventListener("onclick ", HidePreferences, false);
			
			foreach(
				selectNodes("//input[@name='_md_pref']", prefs),
				function(box){
					box.addEventListener("onclick", setPreference, false);
				} );
		}
		prefs.style.display="";
	}
	
	// These are the sites we can link to.
	var movieSiteIDs = [
		"imdb", "netflix", "yahoo", "amazon", "bb", "rotten","piratebay", "ebert", "fcl", "aadl",
	];
	
	var siteNames = {
		netflix: "NetFlix",
		imdb: "IMDb",
		bb: "Blockbuster",
		amazon: "Amazon",
		yahoo: "Yahoo",
		rotten: "Rotten Tomatoes",
		piratebay: "The Pirate Bay",
		ebert: "Ebert",
		fcl: "FCL",
		aadl: "AADL"
	}
		
	// The CSS class to get the movie title from	
	var siteXPath = {
		bb: "//*[@class='headline1']",
		yahoo: "//td/h1/strong|//td/big/b",
//		rotten: "//div[@id='title']/h1",
		rotten: "//td/h1",
		ebert: "//span[@class='moviename']",
		amazon: "//b[@class='sans']"
	}
	
	// How to link to site "key"
	var tUrlToSearchPage = {
		netflix: "http://www.netflix.com/Search?v1={search}&type=title&row=title&dtl=1",
		imdb: "http://imdb.com/find?q={search};tt=on;nm=on;mx=20",
		bb: "javascript:document.forms['_md_bb_search'].submit()",
		amazon:  "javascript:document.forms['_md_amazon_search'].submit()",
		yahoo: "http://movies.yahoo.com/mv/search?p={search}",
		rotten: "http://www.rottentomatoes.com/search/full_search.php?search={search}",
		piratebay: "http://thepiratebay.org/search.php?video=1&q={search}",
		ebert: "javascript:document.forms['_md_ebert_search'].submit()",
		fcl: "http://hip.farmlib.org/ipac20/ipac.jsp?&profile=dial--1&index=FTL&term={search}&x=0&y=0&aspect=basic_search",
aadl: "http://www.aadl.org/cat/seek/search/X?SEARCH={search}&searchscope=26&x=0&y=0&SORT=D",
	}
	
	var siteIcons = {
		imdb: "http://imdb.com/favicon.ico",
		netflix: "http://cdn.nflximg.com/us/icons/nficon.ico",
		amazon: "http://www.amazon.com/favicon.ico",
		yahoo: "http://www.yahoo.com/favicon.ico",
		rotten: "http://www.rottentomatoes.com/favicon.ico",
		piratebay: "http://piratebay.org/favicon.ico",
		ebert: "http://www.yezbick.com/ebert.ico",
		fcl: "http://www.yezbick.com/fcllogo.ico",
		aadl: "http://www.aadl.org/favicon.ico",
	}
	
	// The hidden Form to inject to link to site "key"
	var tForm = {
		bb: [
			{id: "_md_bb_search", 
			 action: "http://blockbuster.com/search/PerformKeyWordSearchAction.action"},
			{schannel: "Movies", keyword: "*", searchType:"Movies"}],
			
		amazon: [
			{id: "_md_amazon_search",
			 action: "http://amazon.com/exec/obidos/search-handle-form/002-3340566-5062428"},
			 {url: "index=dvd", "field-keywords": "*"}],
			 
		ebert: [
			{id: "_md_ebert_search",
  			 action: "http://rogerebert.suntimes.com/apps/pbcs.dll/classifieds?category=search3"},
  			 {
				Class: "60",
				Type: "",
				FromDate: "19150101",
				ToDate: "20051231",
				Start: 1,
				SortOrder: "AltTitle",
				Genre: "",
				GenreMultiSearch: "",
				RatingMultiSearch: "",
				MPAASearch: "",
				SearchType: "1",
				qrender: "",
				Partial: "",
				q: "*"}],
	}
	
	function GetHTML(_fromSite, _linkTo, _movie){
		var link = tUrlToSearchPage[_linkTo].template( {search: encodeURIComponent(_movie)} );
		var html = " &bull; <a href=\"{href}\">{name}</a>".template( {
			href: link, 
			name: siteNames[_linkTo]} );
		
		if (GM_getValue("_icons",true)){
			var icon = siteIcons[_linkTo] || noFavicon;
			html += " <img src='" + icon + "' width='16' height='16' border='0' />";
		}
		return html;
	}
	
	function GetForm(formAttrs, formFields,_movie){
		var field = "<input type=\"hidden\" name=\"{name}\" value=\"{value}\">"
		var form_attr = " {name}=\"{value}\"";
		
		var s = "<form method=\"post\" style=\"display:none;\"";
		foreach_dict(formAttrs, function(k,v){s += form_attr.template({name:k,value:v});});
		s += ">";
		foreach_dict(formFields, function(k,v){
			if (v=="*") { v=_movie; }
			s += field.template({name:k,value:v});
			}
		);
		s += "</form>";
		
		return s;
	}
	
	function removeBrackets(movieName){
		do {
			var bracketIndex = movieName.indexOf("(");
			if (-1 == bracketIndex) bracketIndex = movieName.indexOf("[");
			if (-1 < bracketIndex) movieName = movieName.substring(0,bracketIndex).trim();
		} while (bracketIndex != -1)
		
		return movieName;
	}
	
	function removeSuffix(movieName){
		foreach([" - Criterion Collection"], function(suffix){
			if (movieName.endsWith(suffix)){
				movieName = movieName.removeSuffix(suffix).trim();
				return true;
			}
		});
		
		return movieName;
	}
	
	function getSiteBeingViewed(){
		var whichSite = null;
		foreach_dict(
			{
				"imdb":"imdb.com",
				"netflix":"netflix.com",
				"bb":"blockbuster.com",
				"yahoo":"movies.yahoo.com",
				"rotten":"rottentomatoes.com",
				"ebert":"rogerebert.suntimes.com",
				"amazon":"amazon.com",
				"fcl":"farmlib.org",
				"aadl":"aadl.org",
			}, 
			function(name, host){
				if ( -1 < location.host.indexOf(host)){
					whichSite = name;
					return true;
				}
			});
			
		// Only link movie-related amazon pages
		if (whichSite == "amazon"){
			var pageTitle = document.title;
			if (!(
				(-1 < pageTitle.indexOf("DVD:")) ||
				(-1 < pageTitle.indexOf("movie info:"))
			)) whichSite = null;
		}
			
		return whichSite;
	}

	function LinkEmUp(){	
		var whichSite = getSiteBeingViewed();
		if (whichSite == null) return;

		var titleNodes = selectNodes(siteXPath[whichSite] || "//*[@class='title']");
		if (!titleNodes) 
			return;

		var titleNode = titleNodes[0];
		var movieName = titleNode.firstChild.nodeValue;
		
		movieName = removeBrackets(movieName);
		movieName = removeSuffix(movieName);
		movieName = movieName.trim();

		var s = "";
		foreach(movieSiteIDs, function(movieSiteID){
			if ((movieSiteID == whichSite) || (!GM_getValue(movieSiteID, true)))
				return;
				
			s += GetHTML(whichSite, movieSiteID, movieName);

			var formDef = tForm[movieSiteID];
			if (formDef) s += GetForm(formDef[0], formDef[1], movieName);
		} );

		titleNode.innerHTML += ( "<span id='_md_links'><br>" + s + "</span>");
		addCSS("#_md_links, #_md_links a {font-size:10pt !important;font-weight:normal !important;text-transform: none !important;}");
	}
	
	GM_registerMenuCommand("Movie Dude Home Page >>", function(){location.href="http://adamv.com/dev/grease/moviedude"});
	GM_registerMenuCommand("Movie Dude Settings...", ShowPreferences);

	LinkEmUp();
})();

