// disable no-javascript message
document.write('<style>form,#tiles { display: block } #no-js { display: none }</style>');

var main_artist,
	play_timer,
	tiles = [],
	data_cache = { amazon: {}, cdbaby: {} },
	xhr,
	center_tile,
	engine = 'amazon';

$(document).bind('contextmenu', function(){ return false });

$(document).ajaxError(function(){
	$('#loading').remove();
	
    if (window.console && window.console.error) {
        console.error(arguments);
    }
});

$.log_all = function(obj, label, except, bonus) {
	label = label || 'object';
	
	$.each(obj, function(key, fn) {
		if (except) {
			for (var k in except) {
				if (except[k] === key) return;
			}
		}
		if (typeof fn == 'function') {
			obj[key] = function(){
				var me = this;
				
				console.log(label + '.' + key, me, arguments, bonus && bonus());
				try {
					return fn.apply(me, arguments);
	            } catch (e) {
	                console.error(label + '.' + key, e);
	                throw e;
	            }
			};
		}
	});
};

// function to find the x, y position of an element (from http://www.quirksmode.org/js/findpos.html)
jQuery.fn.findPos = function() {
	var obj = this[0], curleft = 0, curtop = 0;
	if (obj && obj.offsetParent) {
		curleft = obj.offsetLeft;
		curtop = obj.offsetTop;
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft;
			curtop += obj.offsetTop;
		}
	}
	return [curleft,curtop];
}

jQuery.fn.scrollBox = function(){
	return this.mousemove(function(e){
		var self = $(this),
			outer_height = self.height(),
			pos = self.findPos(),
			inner_height = self.children('ul').height(),
			offset = e.pageY - pos[1];
		
		self[0].scrollTop = Math.min(inner_height - outer_height, (offset / outer_height) * inner_height - (outer_height * 3/4));
	});
};

var guid = 0,
	CENTER_POS = 4;

var ArtistTile = function(data){
	this.data = data;
	
	this.id = 'artist_tile_' + (guid++);

	this.create();
};
ArtistTile.prototype = {
	create: function(){
		var me = this,
			album = this.data.name,
			artist = this.data.artist || main_artist;
		
		// a method of htmldecoding
		album = album ? $('<div/>').html(album).text() : album;
		
		var el = $('<div>')
					.hide()
					.addClass('artist-tile')
					.attr('id', this.id)
					.attr('title', artist + ': ' + album)
					.hover(function(){
						$('a', this).show();
					}, function(){
						$('a', this).hide();
					})
					.click(function(){
						// $('#artist').val(name);

						center_tile = me;

						$.historyLoad(get_key(artist, album));

						me.position($(this), CENTER_POS);
						
					})
					.Draggable({
						ghosting: true,
						revert: true,
						opacity: 0.5,
						fx: 500,
						containment: 'document',
						insideParent: true
					})
					.appendTo('#tiles');

		var indie_artist = artist;
		
		var buttons = [
				// amazon affiliate link/icon
				{
					className: 'amazon-link',
					href: 'http://www.amazon.com/gp/search?ie=UTF8&keywords=' + encodeURIComponent(indie_artist) + '&tag=monecom&index=music&linkCode=ur2&camp=1789&creative=9325',
					title: indie_artist + ' albums at Amazon'
				},
				// itunes affiliate link/icon
				{
					className: 'itunes-link',
					href: 'itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?artistTerm=' + encodeURIComponent(indie_artist) + '&partnerId=30&siteID=B.vJnPysYUk-RT7hBK3X4q4xyscD0OQr8w',
					title: indie_artist + ' albums at iTunes'
				}
		];
		
		if (!/^http:/.test(me.data.href)) {
			// cdbaby affiliate link/icon
			buttons.push({
				className: 'cdbaby-link',
				href: 'http://cdbaby.com' + me.data.href + '/from/acfou',
				title: album + ' at CD Baby'
			});
		}
		
		if (FACEBOOK) {
			// facebook share link
			buttons.push({
				className: 'mailto-link',
				href: '#share',
				title: 'Share with a friend',
				onclick: function(){
					share_music(artist, album);
					return false;
				}
			});
		} else {
			// mailto link/icon
			buttons.push({
				className: 'mailto-link',
				href: 'mailto:?subject=' + encodeURIComponent('someone sent you a mreeting (music + greeting)') + '&body=' + encodeURIComponent('Here are some indie musicians whose music is like ' + main_artist + ':') + '%0A%0A' + encodeURIComponent('http://musicsamplr.com/cdbaby/#'+ encodeURIComponent(get_key(album, main_artist))),
				title: 'Share with a friend'
			});
		}
		
		$.each(buttons, function(i, button) {
			$('<a/>')
				.attr('href', button.href)
				.attr('target', '_blank')
				.attr('title', button.title)
				.addClass(button.className)
				.click(function(e){
					e.stopPropagation();

					if (button.onclick) {
						return button.onclick();
					}
				})
				.appendTo(el);
		});

		this.position(el, this.data.pos);

		var img = $('<img/>')
			.load(function(){
				el.fadeIn(2000);
			})
			.attr({
				src: this.data.image,
				width: 150,
				height: 150
			})
			.appendTo(el);
	},
	get: function(){
		return $('#' + this.id);
	},
	position: function(el, pos) {
		var row = Math.floor(pos / 3),
			col = pos % 3,
			left = (col * 180),
			top = (row * 180);
		
		if (typeof(this.pos) !== 'undefined') {
			el.animate({
				left: left,
				top: top
			}, 2000);
		} else {
			el.css({
				position: 'absolute',
				left: left,
				top: top
			});
		}

		this.pos = pos;
	}
};

var Playlist = {
	list: [],
	pos: 0,
	sample_length: 0,
	
	start: function(list) {
		this.clear();
		
		this.list = list;
		this.play();
	},
	
	get_itunes: function(artist, song){
		if (!artist || !song) return;

		var indie_artist = artist, album = '';
		if (artist.indexOf(':') != -1) {
			var split = artist.split(':');
			indie_artist = split[0];
			album = split[1];
		}

		return $('<a/>')
				.attr('href', 'itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?songTerm=' + encodeURIComponent(song) + '&artistTerm=' + encodeURIComponent(indie_artist) + '&albumTerm=' + encodeURIComponent(album) + '&partnerId=30&siteID=B.vJnPysYUk-RT7hBK3X4q4xyscD0OQr8w')
				.attr('title', 'Download ' + song + ' by ' + indie_artist + ' at iTunes')
				.click(function(e){
					e.stopPropagation();
				})
				.addClass('itunes-link');
	},
	
	now_playing: function (artist, song) {
		if (!artist || !song) return;
		
		$('#now-playing').text(artist + ' - ' + song);
		$('#controls').show();
		
		var itunes = this.get_itunes(artist, song);
	
		$('#now-playing-row').find('a').remove().end().append(itunes);
	
		// if playlist box is open, add to it
		this.refresh_box();
		
		return this;
	},
	
	clear: function(){
		Playlist.list = Playlist.played = [];
		Playlist.close();
		this.pos = 0;
		return this;
	},
	
	refresh_box: function(box) {
		var me = this,
			box = box || $('#playlist');
		
		if (!box[0]) return;

		var ul = $('ul', box);
		ul.empty();
		
		$.each(this.list, function(i, item){
			var li = $('<li/>')
						.html(item.artist + ' - ' + item.name)
						.click(function(){
							Playlist.play_item(i);
							
							Playlist.close();
						})
						.hover(function(){
							$(this).addClass('hover');
						}, function(){
							$(this).removeClass('hover');
						})
						.append(me.get_itunes(item.artist, item.name))
						.appendTo(ul);
			
			if (i == me.pos) {
				li.addClass('playing');
			}
		});

		var li_height = $('li:eq(0)', ul).height();
		box.height(li_height * Math.min(this.list.length, 9));
		box.css('bottom', -li_height * Math.min(Math.ceil(this.list.length / 2), 5));

		return this;

	},
	
	open: function() {
		var box = $('<div id="playlist"><div></div><ul></ul></div>').appendTo('#now-playing-row');
		
		box.scrollBox();
		
		this.refresh_box(box);
		
		$('#now-playing').hide();
		
		$('body').click(Playlist.close);
		
		window.scrollTo(0, 5000);
	},
	
	close: function(){
		$('#playlist').remove();

		$('#now-playing').show();

		$('body').unbind('click', Playlist.close);
	},
	
	play_url: function(url, next_url){
		if (!flash_enabled) return;

		// swap old and new
		var old = this.old_player;
		this.old_player = this.player;
		this.player = old;

		$('#__music_player__').remove();

		if (url.indexOf('mp3') == -1) {
			$("<div id='__music_player__'></div>")
				.appendTo('body')
	        	.html('<embed src="' + url + '" autostart="true" width="0" height="0" loop="false"></embed>');
		} else {
			if (this.next_url != url) {
				// we just started streaming, so we have to load song now
				this.player.loadSound(url, true);
			} else {
				// we have the url preloaded, so just start playing
				this.player.start();
			}
		}

		// do a 2-second "fade"
		if (this.ever_played) { // skip on the first play
			clearInterval(this.swap_timeout);
			this.swap_timeout = setTimeout(function(){
				if (next_url.indexOf('mp3') != -1 && next_url.indexOf('wma') != -1) {
					Playlist.next_url = next_url;
					Playlist.old_player.loadSound(next_url, false);
				}
				else {
					Playlist.old_player.stop();
				}
			}, 2000);
		}
				
		this.ever_played = true;
	},
	
	get_item: function(i) {
		return this.list[i % this.list.length];
	},
	
	play_item: function (i) {
		var list = this.list;
		
		// loop back to start
		if (i >= list.length) {
			// if we're looping to the start but still haven't played any music, give up
			if (!this.played_anything) return;
	
			// loop to start
			i = 0;	
		}
	
		this.pos = i;
	
		var item = list[i];
		if (!item) return;
	
		var url = '' + item.url;
		
		if (flash_enabled) {
			if (url.indexOf('swf') != -1) {
				var movie_element = [
	        		'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="0" height="0"',
	        		' align="middle">',
	        		'<param name="movie" value="'+url+'" />',
	        		'<param name="quality" value="high" />',
	        		'<param name="bgcolor" value="#ffffff" />',
	        		'<param name="allowScriptAccess" value="always"/>',
	        		'<embed src="'+url+'"',
	        		' allowScriptAccess="always" quality="high" bgcolor="#ffffff" width="0" height="0"',
	        		' align="middle" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />',
	        		'</object>'
				].join('');
		
	            var element = document.createElement("div");
	            element.id = "__music_player__";
	            document.body.appendChild(element);
		        document.getElementById('__music_player__').innerHTML += movie_element; 
				this.played_anything = true;
	
				this.now_playing(item.artist, item.name);

			} else if (url.indexOf('flv') != -1) {
				// flv? skip it
				this.play_item(i + 1);
				return;

			} else { // hopefully mp3 or wma
				this.play_url(url, this.get_item(i + 1).url);
				this.played_anything = true;
	
				this.now_playing(item.artist, item.name);
			}
			
		} else {
			if (url.indexOf('mp3') != -1 && url.indexOf('wma') != -1) {
				// use quicktime to play, at least, the first mp3
				var qt_element = '<object type="audio/mpeg" data="' + url + '">'
								+'  <param name="src" value="' + url + '">'
								+'  <param name="autoplay" value="true">'
								+'  <param name="autoStart" value="1">'
								+'</object>';
				
				$('<div id="__music_player__">').appendTo('body').html(qt_element).css({position: 'absolute', right: 0, top: 0 });
				
				this.played_anything = true;
				
				return;
			} else {
				this.play_item(i + 1);
				return;
			}
		}
		
		// question: when to start playing the next song?
		// answer: Playlist.sample_length% of the song, minimum 20 seconds
		// if we can't find the length of the song, default to 20 seconds.
		// we will check in 15 seconds and subtract that from the time
		clearTimeout(Playlist.play_timer);
		Playlist.play_timer = setTimeout(function(){
			var next_song = 20000;
			var song_length = Playlist.player.getDuration();
			if (song_length) {
				next_song = Math.ceil(Math.max(20000, song_length * Playlist.sample_length / 100));
			}
			
			clearTimeout(Playlist.play_timer);
			Playlist.play_timer = setTimeout(function(){
				Playlist.play_item(i + 1);
			}, next_song - 15000);
		}, 15000);
	},
	
	play: function () {
		this.played_anything = false;
	
		this.play_item(Playlist.pos);
	},
	
	pause: function (){
		clearTimeout(Playlist.play_timer);

		this.player.stop();
		this.old_player.stop();

		$('#__music_player__').remove();
	},

	stop: function (){
		this.pause();
		$('#controls').hide();
	}
};

//$.log_all(Playlist, 'playlist');

function clear_all(except) {
	var the_exception;
	
	while (tiles.length) {
		var tile = tiles.pop();
		if (!except || tile.id != except.id) {
			tile.get().Puff(2000, function(){ $(this).remove() });
		} else {
			the_exception = tile;
		}
	}
	
	if (the_exception) tiles = [ the_exception ];
}

function load_artist(artist, album) {
	var data = get_cache(artist, album);
	
	if (center_tile && center_tile.data.name != data.artist.name) {
		center_tile.get().remove();
		center_tile = false;
		tiles = [];
	}
	if (!center_tile) {
		data.artist.pos = CENTER_POS;
		center_tile = new ArtistTile(data.artist);
		tiles.push(center_tile);
	}
	
	$.each(data.related, function(i, artist) {
		artist.pos = (i < CENTER_POS ? i : i + 1)
		tiles.push(new ArtistTile(artist));
	});
	
	// start playing the most played
	Playlist.start(data.songs);

	// preload data from the other tiles
	preload();
}

function cache(data, artist, album, eng) {
	data_cache[get_key(artist, album, eng)] = data;
}
function get_cache(artist, album, eng) {
	return data_cache[get_key(artist, album)] || false;
}

function get_key(artist, album, eng) {
	eng = eng || engine;
	
	return (album ? album + '||' : '') + artist + '||' + eng;
}
function preload() {
	if (xhr) xhr.abort();
	
	for (var i=0,l=tiles.length;i < l;i++) {
		var album = tiles[i].data.name,
			artist = tiles[i].data.artist || main_artist;
		
		if (!get_cache(artist, album)) {
			xhr = $.ajax({
				url: DATA_PATH,
				type: 'POST',
				data: {
					artist: artist,
					album: album,
					refer: main_artist,
					engine: engine
				},
				dataType: 'json',
				success: function(data){
					cache(data, artist, album);
					xhr = false;
					preload();
				}
			});
			return false;
		}
	}
}

$().keydown(function(e){
	if (e.keyCode == 27) {
		Playlist.stop();
	}
});

function do_search(artist, album) {
	if (!artist) return;
	
	artist = artist.toLowerCase();
	key = get_key(artist, album);
	Playlist.pos = 0;
	
	clearTimeout(play_timer);
	$('#loading').remove();

	$('p.might-like').show().find('span').text(main_artist);
	
	if (get_cache(artist, album)) {
		load_artist(artist, album);
	} else {
		$('form').append('<span id="loading">loading...</span>');
		
		if (xhr) xhr.abort();
		
		xhr = $.ajax({
			url: DATA_PATH,
			type: 'POST',
			data: {
				artist: artist,
				album: album || '',
				refer: main_artist || '',
				engine: engine
			},
			dataType: 'json',
			success: function(data){
				cache(data, artist, album);
				load_artist(artist, album);
				
				$('#loading').remove();
				xhr = false;
			}
		});
/*		
		// cache the other engine, if not cached already
		var other_engine = (engine == 'cdbaby' ? 'amazon' : 'cdbaby');
		if (!get_cache(artist, album, other_engine)) {
			$.ajax({
				url: DATA_PATH,
				type: 'POST',
				data: {
					artist: artist,
					album: album || '',
					refer: main_artist || '',
					engine: other_engine
				},
				dataType: 'json',
				success: function(data){
					cache(data, artist, album, other_engine);
				}
			});
		}
*/
	}
}

$(function(){
	Playlist.old_player = new Sound({ swfLocation: PATH + "flash/SoundBridge.swf" });
	Playlist.player = new Sound({ swfLocation: PATH + "flash/SoundBridge.swf" });
	
	$('#pause').toggle(function(){
		Playlist.pause();
		this.src = PATH + 'images/play-btn.png';
	}, function(){
		Playlist.play();
		this.src = PATH + 'images/pause-btn.png';
	});
	
	$('#now-playing').toggle(function(){
		Playlist.open();
	}, function(){
		Playlist.close();
	});
	
	$('form').submit(function(){
		main_artist = $('#artist').val();

		center_tile = false;

		clear_all();

		$.historyLoad(get_key(main_artist));
		
		return false;
	});

	$('#sample-slider').Slider({
		accept: '.handle',
		values: [ [ 0, 100 ] ],
		restricted: true,
		onChange: function(amount){
			Playlist.sample_length = amount * 0.9;
		}
	});

	
	if ($('#artist').val() == '' || $('#artist').val() == 'type artist name') {
		$('#artist')
			.css('color', '#aaa')
			.val('type artist name')
			.focus(function(){
				$(this).val('').css('color', '#000');
			});
	}
	
	$('#plugoo-link').toggle(function(){
		var pos = $(this).findPos();
		
		$('#plugoo')
			.css({
				top: pos[1] + $(this).height(),
				left: pos[0]
			})
			.slideDown();
			
		$(this).text('[-] feedback');
	}, function(){
		$('#plugoo').slideUp();

		$(this).text('[+] feedback');
	});
	
	$('#tabs li')
		.click(function() {
			change_engine(this.id);
		});
	
	$('#envelope').Droppable({
		accept: 'artist-tile',
		tolerance: 'pointer',
		//activeclass: 'active',
		hoverclass: 'hover',
		ondrop: function(tile){
			location.href = $('a.mailto-link', tile)[0].href;
		}
	});
	
	$.historyInit(function(hash) {
		var artist, album, eng;
		if (hash.indexOf('||') != -1) {
			var split = hash.split('||');
			if (split.length == 3) {
				album = split[0];
				artist = split[1];
				eng = split[2] || engine;
			} else {
				artist = split[0];
				eng = split[1] || engine;
			}
			change_engine(eng);
			main_artist = artist;
		} else {
			main_artist = artist = hash;
		}
		
		clear_all(center_tile);
		do_search(artist, album);
	});
});


var flash_enabled = (function() {
	if (navigator.plugins && navigator.plugins.length) {
		return !!(navigator.plugins["Shockwave Flash"] || navigator.plugins["Shockwave Flash 2.0"]);
	}
	else if (navigator.mimeTypes && navigator.mimeTypes.length)	{
		return !!(navigator.mimeTypes['application/x-shockwave-flash'] && navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin);
	}
	else {
		for(var i=7; i>0; i--){
			flashVersion = 0;
			try{
				var flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + i);
				return i;
			}
			catch(e){
			}
		}
	}
	return false;
})();

function change_engine(set_engine) {
	if (engine == 'amazon') {
		$('#slider-wrap').hide();
	} else {
		$('#slider-wrap').show();
	}

	if (set_engine == engine) return;
	
	$('#tabs li').removeClass('selected');
	$('#' + set_engine).addClass('selected');
	
	// this might throw errors initially
	try {
		Playlist.stop();
	} catch(e) {}
	
	clear_all();
	
	engine = set_engine;
	clearInterval(play_timer);
	center_tile = null;
	
	// redo search
	$.historyLoad(get_key(main_artist));
}

function share_music(artist, album, song) {
	top.location.href = 'http://apps.facebook.com/musicsamplr/compose/' + encodeURIComponent(artist) + '/' + encodeURIComponent(album);
}
