// disable text selection to disallow borking album cover selection
$.fn.disableSelection = function() {
	$(this).attr('unselectable', 'on').css('-moz-user-select', 'none').each(function() { 
		this.onselectstart = function() { return false; };
	});
};

// meh, bad api from youtube...
var onYouTubePlayerReady = function(playerid) {
	mashmush.youtube.player().addEventListener("onStateChange", "(function() { mashmush.evl();})()");
};

var mashmush = {
	
	// information about albums
	albumlist: {
		albums: [],
		cue: 0,
		visibleCue: 0
	},
	
	// playlist of current album
	playlist: {
		songs: [],
		cue: 0
	},
	
	// the current song's cue on youtube keyword search
	currentSongCue: 0,
	
	// coverflow management
	coverflow: undefined,
	timeout: {
		timer: undefined,
		delay: 20000,
		
		go: function() {
			if (mashmush.timeout.timer !== undefined)
				window.clearTimeout(mashmush.timeout.timer);
			
			mashmush.timeout.timer = window.setTimeout(mashmush.timeout.clear, mashmush.timeout.delay);
		},
		
		clear: function() {
			window.clearTimeout(mashmush.timeout.timer);
			
			if (mashmush.albumlist.cue !== mashmush.albumlist.visibleCue)
				mashmush.coverflow.glideTo(mashmush.albumlist.cue);
		}
	},
	
	fadeable: {
		timer: undefined,
		delay: 20000,
		
		bind: function() {
			$(window).bind("mousemove", function() {
				mashmush.fadeable.reset();
			});
		},
		
		reset: function() {
			if (mashmush.fadeable.timer !== undefined)
				window.clearTimeout(mashmush.fadeable.timer);
			
			mashmush.fadeable.fadein();
			mashmush.fadeable.timer = window.setTimeout(mashmush.fadeable.fadeout, mashmush.fadeable.delay);
		},
		
		fadeout: function() {
			if (mashmush.textWithFocus) return;
			$(".fadeable").fadeOut();
		},
		
		fadein: function() {
			$(".fadeable").fadeIn();
		}
	},
	
	// search box stuff & fluff
	textWithFocus: false,
	autocompleteCache: {},
	
	// chrome extension fluff
	chrome: {
		sendableEvent: undefined
	},
	
	init: function() {
		mashmush.youtube.init();
		mashmush.bind();
	},
	
	hideControls: function() {
		if ($("#nowplaying").css("display") != "none") {
			$("#nowplaying").fadeOut();
			$("#controls").fadeOut().removeClass("fadeable");
		}
	},
	
	showControls: function() {
		if ($("#nowplaying").css("display") == "none") {
			$("#nowplaying").fadeIn();
			$("#controls").fadeIn().addClass("fadeable");
		}
	},
	
	nextVersion: function() {
		mashmush.play(mashmush.currentSongCue+1);
	},
	
	status: function() {
		var song = mashmush.playlist.songs[mashmush.playlist.cue];
		
		if (song !== undefined) {
			mashmush.sendEventToChromeExtension({
				isStatus: "status",
				type:   $("#playpause").text() == "pause" ? "play" : "pause",
				artist: song.creator,
				album:  song.album,
				title:  song.title
			});
		}
		else {
			mashmush.sendEventToChromeExtension({
				isStatus: "status",
				type:   undefined,
				artist: undefined,
				album:  undefined,
				title:  undefined
			});
		}
	},
	
	play: function(position) {
		var p = position || 0;
		mashmush.currentSongCue = p;
		mashmush.timeout.clear();
		
		var song = mashmush.playlist.songs[mashmush.playlist.cue];
		var keyw = [song.creator, song.album, song.title].join(" ");
		mashmush.youtube.playVideoByKeywords(keyw, p);
		
		$("#nowplaying-artist").text(song.creator);
		$("#nowplaying-album").text(song.album);
		$("#nowplaying-music").text(song.title);
		
		mashmush.sendEventToChromeExtension({
			type:   "play",
			artist: song.creator,
			album:  song.album,
			title:  song.title
		});
		
		$("#playpause").text("pause");
	},
	
	pause: function() {
		if (mashmush.youtube.player() && mashmush.youtube.player().pauseVideo)
			mashmush.youtube.player().pauseVideo();
		
		mashmush.sendEventToChromeExtension({type:"pause"});
		$("#playpause").text("play");
	},
	
	playFocusedAlbum: function() {
		mashmush.pause();
		mashmush.albumlist.cue = mashmush.albumlist.visibleCue;
		mashmush.timeout.clear();
		
		var mbid = mashmush.albumlist.albums[mashmush.albumlist.cue].mbid;

		mashmush.lastfm.musicsByAlbum(mbid, function(data) {
			if (data.error === -1000) {
				mashmush.hideControls();
				return;
			}
			
			mashmush.playlist.cue = 0;
			mashmush.playlist.songs = $.map(data.playlist.trackList.track, function(song, i) {
				return {creator: song.creator, album: song.album, title: song.title};
			});

			mashmush.play();
			mashmush.showControls();
		});
	},
	
	playpause: function() {
		if (mashmush.youtube.player().getPlayerState() == 1) {
			// playing
			mashmush.youtube.player().pauseVideo();
			mashmush.sendEventToChromeExtension({type:"pause"});
			$("#playpause").text("play");
		}
		else if (mashmush.youtube.player().getPlayerState() == -1) {
			mashmush.playFocusedAlbum();
		}
		else {
			mashmush.youtube.player().playVideo();
			$("#playpause").text("pause");
		}
	},
	
	next: function() {
		if (mashmush.playlist.cue < mashmush.playlist.songs.length - 1) {
			mashmush.youtube.player().pauseVideo();
			mashmush.playlist.cue++;
			
			mashmush.play();
		}
		else {
			mashmush.nextAlbum();
		}
	},
	
	prev: function() {
		if (mashmush.playlist.cue > 0) {
			mashmush.youtube.player().pauseVideo();
			mashmush.playlist.cue--;
			
			mashmush.play();
		}
	},
	
	nextAlbum: function() {
		mashmush.youtube.player().pauseVideo();
		
		mashmush.albumlist.visibleCue++;
		mashmush.coverflow.glideTo(mashmush.albumlist.visibleCue);
		
		mashmush.playFocusedAlbum();
	},
	
	prevAlbum: function() {
		if (mashmush.albumlist.cue > 0) {
			mashmush.youtube.player().pauseVideo();

			mashmush.albumlist.visibleCue--;
			mashmush.coverflow.glideTo(mashmush.albumlist.visibleCue);

			mashmush.playFocusedAlbum();
		}
	},
	
	videoDismiss: function(e) {
		mashmush.video(false);
	},
	
	video: function(state) {
		if (state) {
			$("#mashplayer").addClass("visible");
			$("body").bind("click", mashmush.videoDismiss);
		}
		else {
			$("#mashplayer").removeClass("visible");
			$("body").unbind("click", mashmush.videoDismiss);
		}
		
		$("#mashplayer").toggleClass("fullscreen", $(window).data('fullscreen-state')).blur();
	},
	
	sendEventToChromeExtension: function(data) {
		if (mashmush.chrome.sendableEvent !== undefined) {
			var hiddenDiv = document.getElementById("mashmushEvent");
			hiddenDiv.innerText = JSON.stringify(data);
			hiddenDiv.dispatchEvent(mashmush.chrome.sendableEvent);
		}
	},
	
	evl: function() {
		mashmush.processEvent(mashmush.youtube.player().getPlayerState());
	},
	
	processEvent: function(state) {
		switch (state) {
			case 0: // ended
				mashmush.next();
				$("#nowplaying-label").text("getting next song");
				break;
			
			case 1: // playing
				$("#nowplaying-label").text("now playing");
				break;
			
			case 2: // paused
				$("#nowplaying-label").text("paused");
				break;
			
			case 3: // buffering
				$("#nowplaying-label").text("buffering...");
				break;
			
			default: // video cued or ready
				$("#nowplaying-label").text("ready");
				break;
		}
	},
	
	artistSearchSubmit: function(e) {
		var t = $("#search-text").val().trim();
		
		if (t != "") {
			$("#nowplaying-artist").text("");
			$("#nowplaying-album").text("");
			
			mashmush.render(t);
		}
		
		$("#search-text").val("").blur();
		
		if (typeof e.preventDefault === "function")
			e.preventDefault();
		
		return false;
	},
	
	aboutDismiss: function(e) {
		$("#aboutbox").fadeOut();
		$("body").unbind("click", mashmush.aboutDismiss);
	},
	
	bind: function() {
		mashmush.fadeable.bind();
		$(document).disableSelection();
		
		$(document).bind("keydown", function(e) {
			mashmush.fadeable.reset();
			if (mashmush.textWithFocus) return;
			
			switch (e.keyCode) {
				case 32: // spacebar
					mashmush.playpause();
					break;
				
				case 10: // enter
				case 13:
					mashmush.playFocusedAlbum();
					break;
				
				case 85:  // U
				case 117: // u
					mashmush.prevAlbum();
					break;
				
				case 73:  // I
				case 105: // i
					mashmush.nextAlbum();
					break;
				
				case 74:  // J
				case 106: // j
					mashmush.prev();
					break;
				
				case 75:  // K
				case 107: // k
					mashmush.next();
					break;
				
				case 76:  // L
				case 108: // l
					mashmush.nextVersion();
					break;
				
				case 86:  // V
				case 118: // v
					mashmush.video(true);
					break;
				
				case 27:  // esc
					mashmush.video(false);
					break;
				
				default:
					break;
			}
		});
		
		$("#search-text").autocomplete({
			minLength: 1,
			// selectFirst: false,
			source: function(request, response) {
				if (request.term in mashmush.autocompleteCache) {
					response(mashmush.autocompleteCache[request.term]);
					return;
				}
				
				mashmush.lastfm.searchArtist(request.term, function(data) {
					var artists = data.results.artistmatches.artist;
					var resultData = $.map(artists, function(item) {
						return {
							value: item.name,
							label: item.name,
							image: item.image[1]["#text"]
						}
					});
					
					mashmush.autocompleteCache[request.term] = resultData;
					response(resultData);
				});
			},
			focus: function(ev, ui) {
				$("#search-text").val(ui.item.label);
				return false;
			},
			select: function(ev, ui) {
				$('#search-text').val(ui.item.label);
				var ret = mashmush.artistSearchSubmit(ev);
				$("#search-text").val("").blur();
				
				return ret;
			},
			close: function(ev, ui) {
				var ret = mashmush.artistSearchSubmit(ev);
				$("#search-text").val("").blur();
				
				return ret;
			}
		}).data("autocomplete")._renderItem = function(ul, item) {
			return $("<li></li>")
				.data("item.autocomplete", item)
				.append("<a>" +
							"<span class='iwrap' style='background-image: url(" + item.image + ");'></span>" +
							"<span class='ilbl'>" + item.label + "</span>" +
						"</a>")
				.appendTo(ul);
		};
		
		$("#search-text").bind("focusin", function(e) { mashmush.textWithFocus = true; });
		$("#search-text").bind("focusout", function(e) { mashmush.textWithFocus = false; });
		
		$("#search-form").bind("submit", function(e) {
			mashmush.artistSearchSubmit(e);
		});
		
		mashmush.chrome.sendableEvent = document.createEvent('Event');
		mashmush.chrome.sendableEvent.initEvent("sendableEvent", true, true);
		
		// there's an artist name in the hash of the URL, trigger the auto-loading, please!
		if (window.location.hash != "") {
			mashmush.render(window.location.hash.replace("#!/", ""));
			$("#search-text").blur();
		}
		else {
			$("#search-text").focus();
		}
		
		$("#prev").bind("click", function(e) { mashmush.prev(); return false; });
		$("#next").bind("click", function(e) { mashmush.next(); return false; });
		$("#nextversion").bind("click", function(e) { mashmush.nextVersion(); return false; });
		
		$("#playpause").bind("click", function(e) {
			mashmush.playpause();
			return false;
		});
		
		$("#about-link").bind("click", function(e) {
			$("#aboutbox").fadeIn();
			$("body").bind("click", mashmush.aboutDismiss);
			return false;
		});
		
		$("#nowplaying-music").bind("click", function(e) {
			mashmush.video(true);
			return false;
		})
		
		$(window).bind('fullscreen-toggle', function(e, state) {
			if ($("#mashplayer").hasClass("visible")) {
				$("#mashplayer").toggleClass("fullscreen", state);
			}
			
			$("body").animate({ "background-color": state ? "#000" : "#fff" }, function() { $("body").toggleClass("fullscreen", state); });
		});
		
		document.getElementById("mashmushEvent").addEventListener('mashmushEvent', function() {
			var eventData = document.getElementById('mashmushEvent').innerText;
			if (typeof mashmush[eventData] == "function") {
				mashmush[eventData]();
			}
		});
	},
	
	render: function(artist) {
		mashmush.pause();
		mashmush.hideControls();
		
		mashmush.albumlist.cue = mashmush.albumlist.visibleCue = 0;
		
		var artistHash = "#!/" + artist.replace(/\s+/g, "_");
		if (decodeURIComponent(window.location.hash) != artistHash)
			window.location.hash = artistHash;
		
		$("head meta[property=og:title]").attr("content", artist);
		$("head meta[property=og:type]").attr("content", "band");
		$("head meta[property=og:url]").attr("content", "http://www.mashmush.com/" + artistHash);
		$("#fblike").remove();
		$('<iframe id="fblike" src="http://www.facebook.com/plugins/like.php?href=' + encodeURIComponent(window.location.href.replace("#!", "music")) + '&amp;layout=button_count&amp;show_faces=false&amp;width=80&amp;action=like&amp;font=lucida+grande&amp;colorscheme=light&amp;height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:80px; height:20px;" allowTransparency="true" class="fadeable"></iframe>').appendTo("body");
		
		$("#nowplaying-artist").attr("href", "http://www.last.fm/music/" + artist.replace(/\s+/g, "+"));
		
		mashmush.lastfm.albumsByArtist(artist, function(data) {
			$("#album-list").empty();
			$("#nowplaying-artist").text(data.topalbums["@attr"].artist);
			
			mashmush.albumlist.albums = [];
			
			$.each(data.topalbums.album, function(i, album) {
				if (album.mbid && album.mbid != "") {
					mashmush.albumlist.albums.push({ name: album.name, mbid: album.mbid, url: album.url });
					$("<img src='" + album.image[3]["#text"] + "'>").appendTo("#album-list");
				}
			});
			
			mashmush.coverflow = null;
			mashmush.coverflow = new ImageFlow();
			mashmush.coverflow.init({
				ImageFlowID: 'album-list',
				captions: false,
				reflections: false,
				slider: false,
				opacity: true,
				preloadImages: false,
				aspectRatio: $("#album-list").width() / $("#album-list").height(),
				imagesHeight: 0.55,
				onGlide: function(i) {
					mashmush.albumlist.visibleCue = i;
					var album = mashmush.albumlist.albums[i];
					$("#nowplaying-album").text(album.name).attr("href", album.url);
					
					mashmush.timeout.go();
				},
				onClick: function() {
					mashmush.playFocusedAlbum();
				}
			});
			
			$(window).resize(function() {
				$("#caption").css({"margin-top": $("#album-list").height() - 300 });
			});
			
			if ($("#caption").css("display") == "none") {
				mashmush.showControls();
				$("#caption").fadeIn();
			}
		});
	},
	
	lastfm: {
		APIROOT: "http://ws.audioscrobbler.com/2.0/?",
		APIKEY: "7178228c6aa30f161ea70993933c4473",
		
		artistCache: {},
		
		
		baseCall: function(method, params, callback) {
			var url = mashmush.lastfm.APIROOT;
			var par = {
				"format": "json",
				"method": method,
				"api_key": mashmush.lastfm.APIKEY
			};
			
			$.extend(par, params);
			url += $.param(par) + "&callback=?";
			
			$.getJSON(url, function(data) {
				callback(data);
			});
		},
		
		searchArtist: function(artistName, callback) {
			mashmush.lastfm.baseCall("artist.search", { artist: artistName, limit: 5 }, callback);
		},
		
		albumsByArtist: function(artistName, callback) {
			mashmush.lastfm.baseCall("artist.getTopAlbums", { artist: artistName, autocorrect: 1 }, callback);
		},
		
		playlistFetch: function(url, callback) {
			mashmush.lastfm.baseCall("playlist.fetch", { playlistURL: url }, callback);
		},
		
		musicsByAlbum: function(mbid, callback) {
			if (mbid === undefined || mbid == "") {
				callback({error:-1000});
				return;
			}
			
			mashmush.lastfm.baseCall("album.getInfo", { mbid: mbid }, function(data) {
				var url = "lastfm://playlist/album/" + data.album.id;
				mashmush.lastfm.playlistFetch(url, callback);
			});
		}
		
	},
	
	youtube: {
		APIROOT: "http://gdata.youtube.com/feeds/api/videos?",
		
		init: function() {
			var params = { allowFullScreen: "true", allowScriptAccess: "always" };
			var atts = { id: "mashplayer", allowfullscreen: "true" };
			swfobject.embedSWF("http://www.youtube.com/apiplayer?enablejsapi=1&version=3&playerapiid=player1&fs=1", 
				"mashplayer", "640", "480", "8", null, null, params, atts, function(e) {
					if (e.success === false) {
						$("#noflash").fadeIn();
					}
				});
		},
		
		player: function() {
			return $("#mashplayer").get(0);
		},
		
		search: function(keywords, callback) {
			var url = mashmush.youtube.APIROOT;
			var par = {
				"alt": "json-in-script",
				"q": keywords
			};
			
			url += $.param(par) + "&callback=?";
			
			$.getJSON(url, function(data) {
				callback(data);
			});
		},
		
		playVideoByKeywords: function(keywords, position, iterated) {
			var p = position || 0;
			
			var simplify = function(kws) {
				return kws.toLowerCase()
				          .replace(/[àáâãäå]/g, "a")
				          .replace(/æ/g,        "ae")
				          .replace(/ç/g,        "c")
				          .replace(/[èéêë]/g,   "e")
				          .replace(/[ìíîï]/g,   "i")
				          .replace(/ñ/g,        "n")               
				          .replace(/[òóôõö]/g,  "o")
				          .replace(/œ/g,        "oe")
				          .replace(/[ùúûü]/g,   "u")
				          .replace(/[ýÿ]/g,     "y");
			};
			
			var simplifiedKeywords = simplify(keywords);
			
			mashmush.youtube.search(simplifiedKeywords, function(data) {
				if (data.feed.entry && data.feed.entry[p] && data.feed.entry[p].id) {
					var video = data.feed.entry[p];
					var vurl = video.id["$t"];
					var vid  = vurl.substring(vurl.lastIndexOf("/")+1);

					mashmush.youtube.player().loadVideoById(vid, 0, "highres");
				}
				else if (iterated === undefined) {
					mashmush.youtube.playVideoByKeywords(simplifiedKeywords.replace(/\(.*\)/, "").trim(), p, true);
				}
				else {
					// borked, no entries and no iteration hack
				}
			});
		}
	}
	
};

$(function() {
	mashmush.init();
});
