﻿/// <reference path="../_development/jquery-1.3.2-vsdoc2.js" />
/// <reference path="jquery.contextMenu/jquery.contextMenu.js" />
/// <reference path="jquery.tagcloud/jquery.tagcloud.js" />
/// <reference path="streamer.js" />
/// <reference path="silverlight.js" />
/// <reference path="swfobject.js" />

/*
if (typeof Helium == "undefined") {
	Helium = {};
}*/


var Helium = {
	version: '1.0'
};

Helium.UI = function() {

	var _windowDimensions = {
		width: undefined,
		height: undefined,
		padding: 15
	}

	var _dimensions = {
		window: _windowDimensions,
		headerLayoutHeight: 0,
		leftLayoutPadding: 6,
		leftContentHeaderHeight: 0,
		playerHeight: 0,
		playQueueHeaderHeight: 0,
		panelResizeHandleWidth: 10,
		columnTime: 40,
		columnRating: 83,
		columnPlaycontrols: 40,
		scrollBarWidth: 24
	}

	var _settings = {
		volumeSliderPosition: 90
	}


	var old_urls = {
		stream: '/pages/streamfile',
		checkfileaccess: '/pages/checkfileaccess',
		image: '/pages/image',
		json_tracks: '/JSON/tracks',
		json_playqueue: '/JSON/playqueue',
		start: '/start',
		search: '/search',
		album: '/album',
		albums: '/albums',
		artist: '/artist',
		artists: '/artists',
		nowplaying: '/nowplaying',
		settings: '/admin/settings'
	}
	var dummy_length = 15;
	var _urls = {
		stream: "location.href='/pages/streamfile.aspx".slice(dummy_length),
		checkfileaccess: "location.href='/pages/checkfileaccess.aspx".slice(dummy_length),
		image: "location.href='/pages/image.aspx".slice(dummy_length),
		json_tracks: "location.href='/JSON/tracks.aspx".slice(dummy_length),
		json_playqueue: "location.href='/JSON/playqueue.aspx".slice(dummy_length),
		start: "location.href='/start.aspx".slice(dummy_length),
		search: "location.href='/search.aspx".slice(dummy_length),
		album: "location.href='/album.aspx".slice(dummy_length),
		albums: "location.href='/albums.aspx".slice(dummy_length),
		artist: "location.href='/artist.aspx".slice(dummy_length),
		artists: "location.href='/artists.aspx".slice(dummy_length),
		nowplaying: "location.href='/nowplaying.aspx".slice(dummy_length),
		settings: "location.href='/admin/settings.aspx".slice(dummy_length)
	}




	function initDimensions() {
		_windowDimensions.height = $(window).height();
		_windowDimensions.width = $(window).width();
		fixDimensions();
	}
	function fixDimensions() {
		fixHeight();
		fixWidth();
	}

	function fixHeight() {
		var docmargin = 30;
		var playerheight = $("#HeliumPlayerContainer").outerHeight();
		var PQHeaderheight = $("#PlayQueueHeader").outerHeight();
		var leftcontainer_padding = 6;

		var MainContentHeaderHeight = $("#MainContentHeader").outerHeight();
		var newheight = _windowDimensions.height - docmargin - $("#HeaderLayoutContainer").outerHeight();
		if (newheight < 200) newheight = 200;

		$("#BodyLayoutContainer").height(newheight);
		$("#LeftLayoutContainer").height(newheight);
		$("#LeftLayoutContainerInner").height(newheight);

		$("#LeftLayoutContainer #MainContentContainer").height(newheight);
		$("#LeftLayoutContainer #MainContentBody").height(newheight - MainContentHeaderHeight - leftcontainer_padding * 2);

		$("#RightLayoutContainer").height(newheight);
		$("#ActivePlaylistContainer").height(newheight - playerheight);
		$("#ActivePlaylistContainer .inner").height(newheight - playerheight - PQHeaderheight - 6);
	}

	function fixWidth() {

		var docmargin = 30;
		var space_between_panels = 10;
		var leftcontainer_padding = 6;
		var rightcontainer_padding = 3;

		var newwidth = _windowDimensions.width - docmargin - $("#LeftLayoutContainer").width() - space_between_panels;

		$("#BodyLayoutContainer").width(_windowDimensions.width - docmargin);
		$("#RightLayoutContainer").width(newwidth);



		$("#ActivePlaylistContainer .inner").width(newwidth - rightcontainer_padding * 2);

		Helium.playlist.fixWidth();
		Helium.tracklist.fixWidth();

		$("#TimeSlider").width(newwidth - 255);
		//$("#VolumeSlider").width(310);
	}

	function createSettingsdialog() {
		$('#SettingsDialog').dialog(
			{
				autoOpen: false,
				modal: true,
				resizable: false,
				draggable: false,
				buttons: {
					"Cancel": function() { $(this).dialog("close"); },
					"Ok": function() { location.href = Helium.UI.urls.settings; }
				}
			}
		);
		$('div#LeftLayoutContainer #MainContentBody #MainMenu a.config').click(function() {
			$('#SettingsDialog').dialog('open');
		});
	}

	function createTagCloud() {
		$('#tagcloud a').tagcloud({
			size: { start: 12, end: 50, unit: "px" },
			color: { start: '#ff95b7', end: '#bb004b' }
		});
	}

	function addHash(url) {
		return "#" + url;
	}

	var _host_url = "";
	function getHostUrl() {
		if (_host_url == "") {
			_host_url = location.protocol + "//" + location.host;
		}
		return _host_url;
	}

	function _addHashToLinks(container) {
		if (container == null) container = "";
		$(container + ' a.addhash').each(function() {
			if (this.href.indexOf("#") == -1) {
				var theurl = this.href;
				if (theurl.indexOf(getHostUrl()) == 0) {
					theurl = theurl.slice(getHostUrl().length);
				}
				this.href = addHash(theurl);
				$(this).removeClass('addhash');
			}
		});
	}

	function trackPageView(requestUrl) {
		try {
			if (Helium.gaTrackingCode) {
				if (typeof pageTracker != "undefined") {
					pageTracker._trackPageview(requestUrl);
				}
			}
		} catch (err) { }
	}


	return {
		initialize: function(cfg) {
			/*if (cfg.extension) {
			for (name in _urls) {
			_urls[name] += cfg.extension;
			}
			}*/

			_addHashToLinks("");

			// Init and change handlers
			$.address.init(function(event) {
				// Do nothing
			}).change(function(event) {
				var requestUrl = event.value;

				if (requestUrl == "/") {
					requestUrl = Helium.UI.urls.start;
				}
				if (requestUrl.length > 1) {
					Helium.UI.showProgress("#LeftLayoutContainerInner");

					$("#LeftLayoutContainerInner").load(requestUrl + " #MainContentContainer", null,
					function(responseText, textStatus, XMLHttpRequest) {
						if (textStatus == "error") {
							$("#LeftLayoutContainerInner").html("Could not load url: " + requestUrl);
						}

						trackPageView(requestUrl);
						createTagCloud();
						createSettingsdialog();
						Helium.tracklist.update();
						fixDimensions();
						_addHashToLinks('#LeftLayoutContainerInner');
					});
				}
			});

			// Set panel widths to 40/60 at startup
			$("#LeftLayoutContainer").width(Math.floor($("#BodyLayoutContainer").width() * 0.4) - 10);
			$("#RightLayoutContainer").width(Math.floor($("#BodyLayoutContainer").width() * 0.6) - 10);

			initDimensions();
			$(window).resize(initDimensions);


			$("#SearchBox").keypress(function(e) {
				if (e.keyCode == '13') {
					var value = $("#SearchBox").val();
					Helium.UI.SearchTracks(value);
				}
			});

			$("#LeftLayoutContainer").resizable(
			{
				handles: 'e',
				minWidth: 100,
				maxWidth: (_windowDimensions.width - 200),
				resize: function(event, ui) {
					fixDimensions();
				}
			});

		},
		showProgress: function(id) {
			// Obs!! nedan är en buggfix med innerHTML för att inte jQuery skall balla ur om #LeftLayoutContainer innehåller för mycket kod
			var obj = document.getElementById(id.slice(1));
			if (obj) {
				obj.innerHTML = "";
			}
			$(id).html("<div class=\"progressLoader\"></div>");

		},
		eval: function(value, prefix, suffix, emptyvalues) {
			if (!emptyvalues) emptyvalues = [];

			if (value != "") {
				if (emptyvalues.indexOf(value) == -1) {
					return prefix + value + suffix;
				}
			}

			return "";
		},
		formatTime: function(seconds) {
			var hour = 0;
			var min = 0;
			var sec = seconds;

			function ZeroPad(num) {
				return (num.toString().length < 2) ? ["0", num.toString()].join("") : num.toString();
			}

			if (sec > 60) {
				min = Math.floor(sec / 60);
				sec = sec % 60;
			}
			if (min > 60) {
				hour = Math.floor(min / 60);
				min = min % 60;
			}

			if (hour > 0) {
				return [hour, ZeroPad(min), ZeroPad(sec)].join(":");
			} else {
				return [min, ZeroPad(sec)].join(":");
			}
		},
		UpdatePlayerTime: function(elapsed, total) {
			var seconds = Math.floor(elapsed);
			if ((elapsed - seconds) == 0) { // Run once a second
				$("#CurrentTime").html(Helium.UI.formatTime(seconds));
				//$("#PlayerDebug").html(Math.floor(100 * elapsed / total));
				//$('#TimeSlider').slider('value', Math.floor(100 * elapsed / total));
				$('#TimeSlider').slider('option', 'max', total);
				$('#TimeSlider').slider('value', seconds);
			}
		},
		BrowseArtist: function(artistid) {
			location.href = addHash(Helium.UI.urls.artist) + '?artistid=' + artistid;
		},
		BrowseAlbum: function(albumid) {
			location.href = addHash(Helium.UI.urls.album) + '?albumid=' + albumid;
		},
		SearchTracks: function(q) {
			q = q.replace(/\s/g, "+").replace(/\?/g, "%3F").replace(/\&/g, "%26");
			location.href = addHash(Helium.UI.urls.search) + '?q=' + q;
		},
		BrowseGenre: function(genre) {
			if (genre != "")
				location.href = addHash(Helium.UI.urls.search) + '?q=genre:' + genre.replace(/\s/gi, "+");
			else
				alert('No genre available');
		},
		BrowseSimilar: function(trackid, genre) {
			location.href = addHash(Helium.UI.urls.search) + '?similarid=' + trackid + '&genre=' + genre.replace(/\s/gi, "+") + "&" + Math.random();
		},
		DownloadStream: function(trackid) {
			window.open(Helium.UI.urls.stream + '?trackid=' + trackid, '_blank');
		},
		html: function() {
			return {
				ArtistLink: function(artist, artistid) {
					return '<a hr' + 'ef="' + addHash(Helium.UI.urls.artist) + '?artistid=' + artistid + '">' + artist + '</a>';
				},
				AlbumLink: function(album, albumid) {
					return '<a hr' + 'ef="' + addHash(Helium.UI.urls.album) + '?albumid=' + albumid + '">' + album + '</a>';
				},
				Rating: function(rating) {
					var step = 255 / 10;
					var ratingurl = "";
					var cssClass = "";
					if (rating == 0) {
						ratingurl = "rating0.png";
						cssClass = "norating";
					}
					else {
						for (var i = 1; i <= 10; i++) {
							if (rating <= Math.floor(step * i)) {
								ratingurl = 'rating' + i + '.png';
								cssClass = "hasrating";
								break;
							}
						}
					}
					if (ratingurl == 'rating0.png') {
						return '&nbsp;';
					} else {
						return '<img src="/images/' + ratingurl + '" class=\"' + cssClass + '\" width=\"80\" height=\"16\" />';
					}
				}
			}
		} (),
		urls: function() {
			return _urls;
		} (),
		addHashToLinks: function(container) {
			_addHashToLinks(container);
		},
		dimensions: function() {
			return _dimensions;
		} (),
		settings: function() {
			return _settings;
		} ()

	}
} ();


Helium.SilverlightPlayer = function() {

	var silverlightsrc = "location.href='/player/HeliumSilverlightPlayer.xaml".slice(15);
	var _initialized = false;
	var _formats = ['mp3', 'wma'];

	var _config = {
		file: '',
		autoplay: true,
		duration: 0,
		bufferlength: 10,
		onPlayerReady: null,
		playerName: 'Silverlight'
	}
	var media = null;
	var listeners = Array();
	var timeint = null;
	var _state = null;

	function spanstring(stp) {
		var hrs = Math.floor(stp / 3600);
		var min = Math.floor(stp % 3600 / 60);
		var sec = Math.round(stp % 60 * 10) / 10;
		var str = hrs + ':' + min + ':' + sec;
		return str;
	}

	function delegate(obj, fcn) {
		return function() {
			return fcn.apply(obj, arguments);
		}
	}

	function stateChanged() {
		var stt = media.CurrentState;
		if (stt != _state) {
			delegateEvent('STATE', [_state, stt]);
			//$("#PlayerDebug").html(_state + "=" + stt);
			_state = stt;
			_config.duration = Math.round(media.NaturalDuration.Seconds * 10) / 10;

			clearInterval(timeint);
			if (stt == "Playing") {
				timeint = setInterval(delegate(this, timeChanged), 100);
			}
		}
	}

	function timeChanged() {
		var pos = Math.round(media.Position.Seconds * 10) / 10;
		delegateEvent('TIME', [pos, _config.duration]);
	}


	function delegateEvent(typ, arg) {
		for (var i = 0; i < listeners.length; i++) {
			if (listeners[i]['type'].toUpperCase() == typ) {
				listeners[i]['func'].apply(null, arg);
			}
		}
	}

	function LoadFile(prm) {
		if (media) {
			_config.file = prm;
			_config.duration = Helium.playlist.GetPlayingTrackData().TrackLength;
			media.Source = prm;
			if (_config.autoplay) { // Silverlight always autoplay
				//Play();
			}
		}
	}

	function Play() {
		if (media) {
			if (_state == 'Playing') {
				media.pause();
			} else {
				media.play();
			}
		}
	}

	function Stop() {
		if (media) {
			media.stop();
		}
	}

	function setScrub(sec) {
		if (media) {
			media.Position = spanstring(sec);
		}
	}

	function setVolume(pct) {
		if (media) {
			media.Volume = pct / 100;
		}
	}

	function readConfig(cfg) {
		if (cfg.onPlayerReady) {
			_config.onPlayerReady = cfg.onPlayerReady;
		}
	}

	return {
		initialize: function(selector, cfg) {
			readConfig(cfg);

			var container_id = "HeliumSilverlightPlayer";
			$(selector).append('<div id="' + container_id + '" class="playerContainer"></div>');

			if (Silverlight.isInstalled('3.0')) {
				_formats.push("m4a");
			}
			Silverlight.createObjectEx({
				source: silverlightsrc,
				parentElement: $('#' + container_id).get(0),
				properties: {
					width: 16,
					height: 16,
					version: '1.0',
					inplaceInstallPrompt: false,
					isWindowless: true,
					background: '#00FF00'
				},
				events: {
					onLoad: Helium.SilverlightPlayer.handleLoad,
					onError: Helium.SilverlightPlayer.handleError
				},
				context: this
			});
		},
		handleLoad: function(pid, tgt, sdr) {
			media = sdr.findName("Media");
			media.BufferingTime = spanstring(_config.bufferlength);
			media.AddEventListener("CurrentStateChanged", delegate(this, Helium.SilverlightPlayer.handleStateChange));
			_state = media.CurrentState;
			setVolume(Helium.UI.settings.volumeSliderPosition);
			_initialized = true;
			if (_config.onPlayerReady) {
				_config.onPlayerReady(Helium.SilverlightPlayer);
			}
		},
		handleError: function(sender, errorArgs) {
			// Create the error message to display.
			var errorMsg = "Silverlight Error: \n\n";

			// Specify error information common to all errors.
			errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
			errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
			errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";

			// Determine the type of error and add specific error information.
			switch (errorArgs.errorType) {
				case "RuntimeError":
					// Display properties specific to RuntimeErrorEventArgs.
					if (errorArgs.lineNumber != 0) {
						errorMsg += "Line: " + errorArgs.lineNumber + "\n";
						errorMsg += "Position: " + errorArgs.charPosition + "\n";
					}
					errorMsg += "MethodName: " + errorArgs.methodName + "\n";
					break;
				case "ParserError":
					// Display properties specific to ParserErrorEventArgs.
					errorMsg += "Xaml File:      " + errorArgs.xamlFile + "\n";
					errorMsg += "Xml Element:    " + errorArgs.xmlElement + "\n";
					errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute + "\n";
					errorMsg += "Line:           " + errorArgs.lineNumber + "\n";
					errorMsg += "Position:       " + errorArgs.charPosition + "\n";
					break;
				case "MediaError":
					if (Helium.FlashPlayer.isReady()) {
						Helium.player.playTrackFallbackToFlash();
						return;
					}
					break;
				default:
					break;
			}
			// Display the error message.
			alert(errorMsg);
		},
		handleStateChange: function() {
			stateChanged();
		},
		addListener: function(type, func) {
			listeners.push({ type: type, func: func });
		},
		getConfig: function() {
			return _config;
		},
		sendEvent: function(typ, prm) {
			switch (typ.toUpperCase()) {
				case 'LOAD':
					LoadFile(prm);
					break;
				case 'PLAY':
					Play();
					break;
				case 'SCRUB':
					setScrub(prm);
					break;
				case 'STOP':
					Stop();
					break;
				case 'VOLUME':
					setVolume(prm);
					break;
			}
		},
		view: true,
		GetState: function() { return _state },
		isReady: function() {
			return _initialized;
		},
		supportedFormats: function() {
			return { override: true, formats: _formats };
		}

	}
} ();


Helium.FlashPlayer = function() {

	var flashsrc = '/player/HeliumFlashPlayer.swf';
	var _initialized = false;
	var _formats = ['mp3'];

	var _config = {
		file: '',
		autoplay: true,
		duration: 0,
		bufferlength: 10,
		onPlayerReady: null,
		playerName: 'Flash'
	}

	var attributes = {
		id: '',
		name: ''
	};

	var media = null;
	var listeners = Array();
	var timeint = null;
	var _state = null;

	function delegate(obj, fcn) {
		return function() {
			return fcn.apply(obj, arguments);
		}
	}


	function stateChanged() {
		var stt = media.GetState();
		if (stt != _state) {
			delegateEvent('STATE', [_state, stt]);
			//$("#PlayerDebug").html(_state + "=" + stt);
			_state = stt;

			clearInterval(timeint);
			if (stt == "Playing") {
				timeint = setInterval(delegate(this, timeChanged), 100);
			}
		}
	}

	function timeChanged() {
		var pos = Math.round(media.GetPosition() / 100) / 10;
		delegateEvent('TIME', [pos, _config.duration]);
	}


	function delegateEvent(typ, arg) {
		for (var i = 0; i < listeners.length; i++) {
			if (listeners[i]['type'].toUpperCase() == typ) {
				listeners[i]['func'].apply(null, arg);
			}
		}
	}

	function LoadFile(prm) {
		if (media) {
			_config.file = prm;
			_config.duration = Helium.playlist.GetPlayingTrackData().TrackLength;
			media.LoadFile(prm);
			if (_config.autoplay) {
				Play();
			}
		}
	}

	function Play() {
		if (media) {
			if (_state == 'Playing') {
				media.PauseFile();
			} else {
				media.PlayFile();
			}
		}
	}

	function Pause() {
		if (media) {
			media.PauseFile();
		}
	}

	function Stop() {
		if (media) {
			media.StopFile();
		}
	}

	function setScrub(sec) {
		if (media) {
			media.SetPosition(sec * 1000);
		}
	}

	function setVolume(pct) {
		if (media) {
			media.SetVolume(pct / 100);
		}
	}

	function readConfig(cfg) {
		if (cfg.onPlayerReady) {
			_config.onPlayerReady = cfg.onPlayerReady;
		}
	}

	return {
		initialize: function(selector, cfg) {
			readConfig(cfg);
		
			var container_id = "HeliumFlashPlayer";
			$(selector).append('<div id="' + container_id + '" class="playerContainer"></div>').find('#' + container_id).append('<div id="' + container_id + 'Object"></div>');

			var flashvars = {
				onLoad: 'Helium.FlashPlayer.handleLoad',
				onError: 'Helium.FlashPlayer.handleError',
				onMediaLoaded: 'Helium.FlashPlayer.handleMediaLoaded',
				onStateChange: 'Helium.FlashPlayer.handleStateChange'
			};

			attributes.id = container_id + 'Object';
			attributes.name = attributes.id;
			var params = {
				id: attributes.id,
				name: attributes.id,
				menu: "false",
				scale: "noScale",
				allowFullscreen: "true",
				allowScriptAccess: "always",
				bgcolor: "#FF0000"
			};

			swfobject.embedSWF(flashsrc, attributes.id, "16", "16", "9.0.0", "", flashvars, params, attributes);

		},
		handleLoad: function() {
			media = document.getElementById(attributes.id);
			_state = media.GetState();
			setVolume(Helium.UI.settings.volumeSliderPosition);
			_initialized = true;
			if (_config.onPlayerReady) {
				_config.onPlayerReady(Helium.FlashPlayer);
			}
		},
		handleError: function(message) {
			alert(message);
		},
		handleMediaLoaded: function(pos) {
			_config.duration = Math.round(media.GetLength() / 100) / 10;
		},
		handleStateChange: function() {
			stateChanged();
		},
		addListener: function(type, func) {
			listeners.push({ type: type, func: func });
		},
		getConfig: function() {
			return _config;
		},
		sendEvent: function(typ, prm) {
			switch (typ.toUpperCase()) {
				case 'LOAD':
					LoadFile(prm);
					break;
				case 'PLAY':
					Play();
					break;
				case 'PAUSE':
					Pause();
					break;
				case 'SCRUB':
					setScrub(prm);
					break;
				case 'STOP':
					Stop();
					break;
				case 'VOLUME':
					setVolume(prm);
					break;
			}
		},
		view: true,
		GetState: function() { return _state },
		isReady: function() {
			return _initialized;
		},
		supportedFormats: function() {
			return { override: false, formats: _formats };
		}

	}

} ();


Helium.player = function() {

	var _player = null;
	var isGoingNext = false;
	var playCounterTimer = null;

	var players = {
		mp3: null,
		m4a: null,
		ogg: null,
		wma: null
	};

	var _currentTrack = {
		filename: '',
		songlength: 0,
		elapsed: 0,
		playCounterUpdated: false
	}

	function addListeners(playerobject) {
		if (playerobject) {
			if (playerobject.view) {
				playerobject.addListener('STATE', stateChange);
				playerobject.addListener('TIME', timeChange);
			} else {
				setTimeout(function() { addListeners(playerobject) }, 100);
			}
		} else {
			setTimeout(function() { addListeners(playerobject) }, 100);
		}
	}

	function updateNowPlaying(url) {
		var trackID = _getPlayingTrackID();

		$("#NowPlayingPanel").load(Helium.UI.urls.nowplaying + "?trackID=" + trackID + " #MainContentContainer", null,
			function(responseText, textStatus, XMLHttpRequest) {
				Helium.UI.addHashToLinks('#NowPlayingPanel');
			}
		);
	}

	function stateChange(oldState, newState) {
		//$("#PlayerDebug").html(oldState + " => " + newState);

		if (newState == "Playing") {
			$("#PlayerControls").addClass("playing");
		} else {
			$("#PlayerControls").removeClass("playing");
		}


		if (newState == "Playing") {
			updateNowPlaying(_player.getConfig().file);
			clearTimeout(playCounterTimer);
			UpdatePlayCounterTimer();
		} else if (newState == "Paused") {
			//Paused
		} else if (newState == "Closed") {
			clearTimeout(playCounterTimer);
			//$("#NowPlayingPanel").html("No file playing");
		}
	}

	function _getPlayingTrackID() {
		var filename = _player.getConfig().file.toLowerCase();
		return _getTrackIDfromUrl(filename);
	}

	function _getTrackIDfromUrl(url) {
		var filename = url;
		if (filename.indexOf("trackid=") != -1) {
			var trackID = filename.slice(filename.indexOf("trackid=") + 8);
			return trackID;
		} else {
			return "";
		}
	}

	function UpdatePlayCounterTimer() {
		if (!_currentTrack.playCounterUpdated) {
			if (_player.GetState() == "Playing") {
				_currentTrack.elapsed++;

				// 240 sek or half the songlength, if song longer than 30 sek
				if ((_currentTrack.elapsed >= Math.min(_currentTrack.songlength / 2, 240)) && (_currentTrack.songlength != 0)) {
					//$("#PlayerDebug").html("Set playcounter!");
					_currentTrack.playCounterUpdated = true;

					if (_currentTrack.songlength > 30) {
						$.post(Helium.UI.urls.json_playqueue, { action: 'update', trackid: _getPlayingTrackID(), lastfm: "true" }, function(data) {
						}, 'json');
					} else {
						$.post(Helium.UI.urls.json_playqueue, { action: 'update', trackid: _getPlayingTrackID(), lastfm: "false" }, function(data) {
						}, 'json');
					}
				}

			}
			playCounterTimer = setTimeout(UpdatePlayCounterTimer, 1000);
		}
	}


	function timeChange(elapsed, total) {
		Helium.UI.UpdatePlayerTime(elapsed, total);
		_currentTrack.songlength = total;
		if ((elapsed >= (total - 0.5)) && (total != 0)) {
			Helium.player.Next();
		}
	}

	function resetPlayer() {
		isGoingNext = false;
		_currentTrack.elapsed = 0;
		_currentTrack.songlength = 0;
		_currentTrack.playCounterUpdated = false;

		if (_player) {
			_player.sendEvent('STOP');
		}
		var td = Helium.playlist.GetPlayingTrackData();
		if (td) {
			_player = players[td.Format];
			if (_player == null) {
				alert(td.Format + "-files not supported for playback, check Settings for more information.");
			}
		}

		if (_player) {
			//$('#PlayerDebugFormat').html(td.Format + ': ' + _player.getConfig().playerName);
		}
	}

	function handlePlayerReady(playerObj) {

		var sf = playerObj.supportedFormats();

		for (var i = 0; i < sf.formats.length; i++) {
			if (sf.override) {
				players[sf.formats[i]] = playerObj;
			} else {
				if (players[sf.formats[i]] == null) {
					players[sf.formats[i]] = playerObj;
				}
			}
		}
		addListeners(playerObj);
	}

	function sendLoadEvent(filename) {
		var trackid = _getTrackIDfromUrl(filename);
		var checkaccessurl = Helium.UI.urls.checkfileaccess + '?trackid=' + trackid;

		$.ajax({
			url: checkaccessurl,
			type: 'GET',
			dataType: 'text',
			success: function(data, textStatus) {
				if (data == "200: OK") {
					if (_player) {
						_player.sendEvent('LOAD', filename);
					}
				} else {
					alert(data);
				}
			},
			error: function(XMLHttpRequest, textStatus, errorThrown) {
				alert(XMLHttpRequest.responseText);
			}
		});

	}


	return {
		initialize: function(selector, cfg) {
			var playercfg = { onPlayerReady: handlePlayerReady };

			if (cfg.players) {
				for (var i = 0; i < cfg.players.length; i++) {
					cfg.players[i].initialize(selector, playercfg);
				}
			}


			$('#VolumeSlider').slider({
				slide: function(event, ui) {
					//$('#VolumeValue').html(ui.value);
					Helium.player.setVolume(ui.value);
				},
				step: 1,
				min: 0,
				max: 100,
				value: Helium.UI.settings.volumeSliderPosition,
				range: 'min'
			});


			$('#TimeSlider').slider({
				slide: function(event, ui) {
					//$('#PlayerDebug').html(ui.value);
					Helium.player.setTime(ui.value);
				},
				step: 1,
				min: 0,
				max: 100,
				range: 'min'
			});


		},
		setVolume: function(value) {
			if (_player) {
				_player.sendEvent('VOLUME', value);
			}
		},
		setTime: function(value) {
			if (_player) {
				//_player.sendEvent('SCRUB', Math.floor((percent / 100) * _currentTrack.songlength));
				_player.sendEvent('SCRUB', value);
			}
		},
		playFile: function(value) {
			resetPlayer();
			if (_player) {
				_currentTrack.filename = value;
				sendLoadEvent(_currentTrack.filename);
			}
		},
		playTrack: function(trackid) {
			resetPlayer();
			if (_player) {
				_currentTrack.filename = Helium.UI.urls.stream + "?trackid=" + trackid;
				sendLoadEvent(_currentTrack.filename);
			}
		},
		playTrackFallbackToFlash: function() {
			var filename = _currentTrack.filename;
			resetPlayer();
			var td = Helium.playlist.GetPlayingTrackData();
			if (td && (td.Format=='mp3') && Helium.FlashPlayer.isReady()) {
				_player = Helium.FlashPlayer;
				sendLoadEvent(filename);
			} else {
				alert("Media error, please check your file");
			}
		},
		Play: function() {
			if (_player) {
				_player.sendEvent('PLAY');
			}
		},
		Stop: function() {
			resetPlayer();
			if (_player) {
				_player.sendEvent('STOP');
			}
		},
		Previous: function() {
			Helium.playlist.PlayPreviousTrack();
		},
		Next: function() {
			if (!isGoingNext) {
				isGoingNext = true;
				setTimeout("Helium.playlist.PlayNextTrack();", 500);
			}
		}


	}
} ();



Helium.playlist = function() {
	var tracklist_container_selector = "";
	var tracklist_selector = "";
	var sortable_settings = {
		opacity: 0.35,
		revert: '100',
		items: 'li',
		stop: function(event, ui) {

			if ($(ui.item).hasClass('ui-draggable')) {
				$(ui.item).removeClass('ui-draggable selected').html('<span>&nbsp;</span>');
				Helium.playlist.EnqueueAt($(ui.item).attr('id'), $(ui.item));
			} else {
				Helium.playlist.MoveEntry($(ui.item).data('TrackData').EntryID, $(ui.item));
			}
		}
	}
	var colwidths = {
		lencol: Helium.UI.dimensions.columnTime,
		ratcol: Helium.UI.dimensions.columnRating,
		plycol: Helium.UI.dimensions.columnPlaycontrols
	}

	function _initialize(data, selector) {
		var output = "";
		tracklist_container_selector = selector;
		tracklist_selector = selector + " .tracklist";

		$(selector).append(createTrackList());

		/*
		$("<li class='heading'>" +
		"<span class='artcol'>Artist</span>" +
		"<span class='titcol'>Title</span>" +
		"<span class='albcol'>Album</span>" +
		"<span class='lencol'>Time</span>" +
		"<span class='ratcol'>Rating</span>" +
		"<span class='plycol'><a href='#' class='removelink' onclick='Helium.playlist.ClearPlaylist();return false;'></a></span>" +
		"</li>")
		.disableSelection()
		.hover(
		function() {
		GetTrackList().removeClass("hovered");
		$(this).addClass("hovered");
		},
		function() {
		GetTrackList().removeClass("hovered");
		}
		)
		.appendTo(tracklist_selector);
		*/

		if (data.ResultSet.Results.length == 0) {
			//$(tracklist_selector).append('<li class="emptyItem"></li>');
		} else {
			for (var i = 0; i < data.ResultSet.Results.length; i++) {
				$(tracklist_selector).append(createTrackRow(data.ResultSet.Results[i]));
			}
		}
		$(tracklist_selector).sortable(sortable_settings);

		Helium.playlist.fixWidth();
		updatePlayQueueHeader();
	}

	function GetPlayingTrackOrderID() {
		var orderid = -1;
		var elem = $(tracklist_selector + " .playing");
		if (elem.get(0) != null) {
			orderid = elem.data("TrackData").OrderID;
		}
		return orderid;
	}
	function GetNextOrderID(elem) {
		var orderid = -1;
		var nextelem = elem.next();
		if (nextelem.get(0) != null) {
			orderid = nextelem.data("TrackData").OrderID;
		}
		return orderid;
	}

	function GetPrevOrderID(elem) {
		var orderid = 0;
		var prevelem = elem.prev('li[class!=heading]');
		if (prevelem.get(0) != null) {
			orderid = prevelem.data("TrackData").OrderID;
		}
		return orderid;
	}

	function _enqueueLast(data) {
		for (var i = 0; i < data.ResultSet.Results.length; i++) {
			$(tracklist_selector).append(createTrackRow(data.ResultSet.Results[i]));
		}
		$(tracklist_selector).sortable('refresh');

		Helium.playlist.fixWidth();

		//debugOrderID();
		updatePlayQueueHeader();
	}

	function _enqueueNext(data) {
		if ($(tracklist_selector + " .playing").get(0) == null) {
			_enqueueLast(data);
			return;
		}

		fixOrderID(data.ResultSet.Results[0].OrderID, data.ResultSet.Results.length)

		for (var i = data.ResultSet.Results.length - 1; i >= 0; i--) {
			$(tracklist_selector + " .playing").after(createTrackRow(data.ResultSet.Results[i]));
		}
		$(tracklist_selector).sortable('refresh');

		Helium.playlist.fixWidth();

		//debugOrderID();
		updatePlayQueueHeader();
	}

	function fixOrderID(orderid, step) {
		GetTrackList().each(
			function() {
				var td = $(this).data('TrackData');
				if (td) {
					if (td.OrderID >= orderid) {
						td.OrderID += step;
					}
				}
			}
		);
	}

	function debugOrderID() {
		// Order id deugging
		GetTrackList().each(
			function() {
				var td = $(this).data('TrackData');
				$(this).find(".artcol b").html(td.OrderID);
			}
		);
	}

	function updatePlayQueueHeader() {
		var outputString = "";
		var trackcount = 0;
		var tracklength = 0;

		GetTrackList().each(
			function() {
				var td = $(this).data('TrackData');
				if (td != null) {
					trackcount++;
					tracklength += td.TrackLength;
				}

			}
		);


		$("#PlayQueueHeader .trackCount").html(" (" + trackcount + " tracks " + Helium.UI.formatTime(tracklength) + ")");
	}

	function _enqueueAt(data, elem) {
		// Correct OrderId for remaining tracks
		var orderid = data.ResultSet.Results[0].OrderID;
		fixOrderID(orderid, 1);

		$(elem).replaceWith(createTrackRow(data.ResultSet.Results[0]));
		$(tracklist_selector).sortable('refresh');

		//debugOrderID();
		updatePlayQueueHeader();

		Helium.playlist.fixWidth();
	}

	function _moveEntry(elem, orderid) {
		orderid++;
		fixOrderID(orderid, 1);
		elem.data('TrackData').OrderID = orderid;
		//debugOrderID();
	}

	function RemoveItem(id) {
		FindByEntryID(id).remove();
		updatePlayQueueHeader();
	}

	function GetTrackList() {
		return $(tracklist_selector + " li[class!=heading]");
	}

	function createTrackList() {
		return '<ul id="PlayQueueTrackList" class="tracklist"></ul>';
	}

	function createTrackRow(TrackData) {
		return $("<li class='track" + TrackData.TrackID + " entry" + TrackData.EntryID + "'></li>")
			.mousedown(
				function() {
					$(this).siblings().removeClass("selected");
					$(this).addClass("selected");
				}
			)
			.hover(
				function() {
					GetTrackList().removeClass("hovered");
					$(this).addClass("hovered");
				},
				function() {
					GetTrackList().removeClass("hovered");
				}
			)
			.dblclick(
				function() {
					Helium.playlist.playTrack($(this).data("TrackData").EntryID);
				}
			)
			.contextMenu(
				{
					menu: 'PlayQueueContextMenu'
				},
				function(action, el, pos) {
					switch (action) {
						case 'play': Helium.playlist.playTrack(el.data("TrackData").EntryID); break;
						case 'remove': Helium.playlist.removeTrack(el.data("TrackData").EntryID); break;
						case 'clearall': Helium.playlist.ClearPlaylist(); break;
						case 'refreshlist': Helium.playlist.RefreshPlaylist(); break;
						case 'browseartist': Helium.UI.BrowseArtist(el.data("TrackData").ArtistID); break;
						case 'browsealbum': Helium.UI.BrowseAlbum(el.data("TrackData").AlbumID); break;
						case 'browsegenre': Helium.UI.BrowseGenre(el.data("TrackData").Genre); break;
						case 'browsesimilar': Helium.UI.BrowseSimilar(el.data("TrackData").TrackID, el.data("TrackData").Genre); break;
						case 'downloadtrack': Helium.UI.DownloadStream(el.data("TrackData").TrackID); break;
					}
				}
			)
			.data("TrackData", TrackData)
			.append(
	    				"<span class='artcol'>" +
		//"<b>" + TrackData.OrderID + "</b>: " + // Debug row
		    				Helium.UI.html.ArtistLink(TrackData.Artist, TrackData.ArtistID) +
		    			"</span><span class='titcol'>" +
							TrackData.Title +
							Helium.UI.eval(TrackData.Subtitle, " (", ")") +
							Helium.UI.eval(TrackData.Remix, " [", "]") +
	    				"</span><span class='albcol'>" +
	    					Helium.UI.html.AlbumLink(TrackData.Album, TrackData.AlbumID) +
	    				"</span><span class='lencol'>" +
	    					Helium.UI.formatTime(TrackData.TrackLength) +
	    				"</span><span class='ratcol'>" +
	    					Helium.UI.html.Rating(TrackData.Rating) +
	    				"</span><span class='plycol'>" +
	    					"<a href='#' class='playlink' onclick='Helium.playlist.playTrack(" + TrackData.EntryID + ");return false;'></a> " +
	    					"<a href='#' class='removelink' onclick='Helium.playlist.removeTrack(" + TrackData.EntryID + ");return false;'></a>" +
	    				"</span>")
	    	.disableSelection();

	}

	function FindByTrackID(id) {
		return $(tracklist_selector + " .track" + id);
	}

	function FindByEntryID(id) {
		return $(tracklist_selector + " .entry" + id);
	}


	return {
		initialize: function(selector) {
			// Initialize Active playlist
			$.getJSON(Helium.UI.urls.json_playqueue, function(data) {
				_initialize(data, selector);
			});
		},
		EnqueueAndPlay: function(trackid) {
			var orderid = GetPlayingTrackOrderID();
			$.post(Helium.UI.urls.json_playqueue, { action: 'add', trackid: trackid, orderid: orderid }, function(data) {
				_enqueueNext(data);
				Helium.playlist.playTrack(data.ResultSet.Results[0].EntryID);
			}, 'json');
			return false;
		},
		EnqueueNext: function(trackid) {
			$.post(Helium.UI.urls.json_playqueue, { action: 'add', trackid: trackid }, function(data) {
				_enqueueNext(data);
			}, 'json');
			return false;
		},
		EnqueueLast: function(trackid) {
			$.post(Helium.UI.urls.json_playqueue, { action: 'add', trackid: trackid }, function(data) {
				_enqueueLast(data);
			}, 'json');
			return false;
		},
		EnqueueAt: function(trackid, elem) {
			var orderid = GetPrevOrderID(elem);
			$.post(Helium.UI.urls.json_playqueue, { action: 'add', trackid: trackid, orderid: orderid }, function(data) {
				_enqueueAt(data, elem);
			}, 'json');
			return false;
		},
		MoveEntry: function(entryid, elem) {
			var orderid = GetPrevOrderID(elem);
			$.post(Helium.UI.urls.json_playqueue, { action: 'move', entryid: entryid, orderid: orderid }, function(data) {
				_moveEntry(elem, orderid);
			});
			return false;
		},
		EnqueueAlbumAndPlay: function(albumid) {
			var orderid = GetPlayingTrackOrderID();
			$.post(Helium.UI.urls.json_playqueue, { action: 'add', albumid: albumid, orderid: orderid }, function(data) {
				_enqueueNext(data);
				Helium.playlist.playTrack(data.ResultSet.Results[0].EntryID);
			}, 'json');
			return false;
		},
		EnqueueAlbumLast: function(albumid) {
			$.post(Helium.UI.urls.json_playqueue, { action: 'add', albumid: albumid }, function(data) {
				_enqueueLast(data);
			}, 'json');
			return false;
		},
		playTrack: function(id) {
			$(tracklist_selector + " .playing").removeClass("playing");
			var entry = FindByEntryID(id);
			entry.addClass("playing");
			Helium.player.playTrack(entry.data("TrackData").TrackID);
		},
		removeTrack: function(id) {
			RemoveItem(id);
			$.post(Helium.UI.urls.json_playqueue, { action: 'remove', entryid: id }, function(data) { });
		},
		PlayNextTrack: function() {
			var playingtrackData = $(tracklist_selector + " .playing").next().data("TrackData");
			if (playingtrackData != null) {
				Helium.playlist.playTrack(playingtrackData.EntryID);
			}
		},
		PlayPreviousTrack: function() {
			var playingtrackData = $(tracklist_selector + " .playing").prev().data("TrackData");
			if (playingtrackData != null) {
				Helium.playlist.playTrack(playingtrackData.EntryID);
			}
		},
		RefreshPlaylist: function() {
			// Clean old data
			$(tracklist_selector).remove();
			Helium.playlist.initialize(tracklist_container_selector);
		},
		GetPlayingTrackData: function() {
			return playingtrackData = $(tracklist_selector + " .playing").data("TrackData");
		},
		fixWidth: function() {
			if (tracklist_selector == "") return;
			var newwidth = $(tracklist_container_selector).width() - 25;

			var showRatingColumn = (newwidth > 500) && ($(tracklist_selector + " li span.ratcol .hasrating").length > 0);
			var showAlbumColumn = newwidth > 400;
			var ratcolWidth = colwidths.ratcol;
			if (!showRatingColumn) {
				ratcolWidth = 0;
			}

			$(tracklist_selector + " li").width(newwidth);
			$(tracklist_selector + " li span.lencol").width(colwidths.lencol);
			$(tracklist_selector + " li span.ratcol").width(ratcolWidth);
			$(tracklist_selector + " li span.plycol").width(colwidths.plycol);

			var restwidth = newwidth - ratcolWidth - colwidths.lencol - colwidths.plycol;
			if (showAlbumColumn) {
				$(tracklist_selector + " li span.artcol").width(Math.floor(restwidth * 0.33));
				$(tracklist_selector + " li span.titcol").width(Math.floor(restwidth * 0.33));
				$(tracklist_selector + " li span.albcol").width(Math.floor(restwidth * 0.33));
			} else {
				$(tracklist_selector + " li span.artcol").width(Math.floor(restwidth * 0.5));
				$(tracklist_selector + " li span.titcol").width(Math.floor(restwidth * 0.5));
				$(tracklist_selector + " li span.albcol").width(0);
			}

			$(tracklist_selector).width(newwidth);
			$(tracklist_selector).height($("#ActivePlaylistContainer .inner").height() - 20);
		},
		GetTrackListSelector: function() {
			return tracklist_selector;
		},
		ClearPlaylist: function() {
			if (confirm('Clear Play Queue?')) {
				GetTrackList().remove();
				$.post(Helium.UI.urls.json_playqueue, { action: 'clearplaylist' }, function(data) { });
				updatePlayQueueHeader();
			}
		}

	}
} ();



Helium.tracklist = function() {

	var tracklist_container_selector = "";
	var tracklist_selector = "";

	var colwidths = {
		lencol: Helium.UI.dimensions.columnTime,
		ratcol: Helium.UI.dimensions.columnRating,
		plycol: Helium.UI.dimensions.columnPlaycontrols
	}

	function _initialize(selector) {
		tracklist_container_selector = selector;
		tracklist_selector = selector + " .tracklist";

		Helium.tracklist.fixWidth();
	}

	function GetTrackList() {
		return $(tracklist_selector + " li[class!=heading]");
	}

	return {
		initialize: function(selector) {
			_initialize(selector);
		},
		update: function() {

			$(tracklist_selector + " li[id]")
				.draggable(
					{
						connectToSortable: Helium.playlist.GetTrackListSelector(),
						helper: 'clone',
						appendTo: '#TrackListDragContainer',
						opacity: 0.35,
						zIndex: 2700,
						containment: 'document',
						revert: 'invalid',
						revertDuration: 100
					}
				)
				.dblclick(
					function() {
						Helium.playlist.EnqueueAndPlay($(this).attr('id'));
					}
				)
				.hover(
					function() {
						GetTrackList().removeClass("hovered");
						$(this).addClass("hovered");
					},
					function() {
						GetTrackList().removeClass("hovered");
					}
				)
				.mousedown(
					function() {
						$(this).siblings().removeClass("selected");
						$(this).addClass("selected");
					}
				)
				.contextMenu(
					{
						menu: 'TrackListContextMenu'
					},
					function(action, el, pos) {
						switch (action) {
							case 'play': Helium.playlist.EnqueueAndPlay(el.attr('id')); break;
							case 'enqueuenext': Helium.playlist.EnqueueNext(el.attr('id')); break;
							case 'enqueuelast': Helium.playlist.EnqueueLast(el.attr('id')); break;
							//case 'browseartist': Helium.UI.BrowseArtist(el.data("TrackData").ArtistID); break;      
							//case 'browsealbum': Helium.UI.BrowseAlbum(el.data("TrackData").AlbumID); break;      
							//case 'browsegenre': Helium.UI.BrowseGenre(el.data("TrackData").Genre); break;      
						}
					}
				)
				.disableSelection();


		},
		fixWidth: function() {
			if (tracklist_selector == "") return;

			var newwidth = $(tracklist_container_selector).width() - (Helium.UI.dimensions.leftLayoutPadding * 2) - Helium.UI.dimensions.scrollBarWidth;
			var showRatingColumn = (newwidth > 500) && ($(tracklist_selector + " li span.ratcol .hasrating").length > 0);

			var ratcolWidth = colwidths.ratcol;
			if (!showRatingColumn) {
				ratcolWidth = 0;
			}

			var showAlbumColumn = ($(tracklist_selector + " li span.albcol").length >= 1);
			var showArtistColumn = ($(tracklist_selector + " li span.artcol").length >= 1);


			$(tracklist_selector + " li").width(newwidth);
			$(tracklist_selector + " li span.lencol").width(colwidths.lencol);
			$(tracklist_selector + " li span.ratcol").width(ratcolWidth);
			$(tracklist_selector + " li span.plycol").width(colwidths.plycol);

			var restwidth = newwidth - ratcolWidth - colwidths.lencol - colwidths.plycol;
			if (!showAlbumColumn) {
				$(tracklist_selector + " li span.artcol").width(Math.floor(restwidth * 0.5));
				$(tracklist_selector + " li span.titcol").width(Math.floor(restwidth * 0.5));
			} else if (!showArtistColumn) {
				$(tracklist_selector + " li span.albcol").width(Math.floor(restwidth * 0.5));
				$(tracklist_selector + " li span.titcol").width(Math.floor(restwidth * 0.5));
			} else {
				$(tracklist_selector + " li span.artcol").width(Math.floor(restwidth * 0.33));
				$(tracklist_selector + " li span.titcol").width(Math.floor(restwidth * 0.34));
				$(tracklist_selector + " li span.albcol").width(Math.floor(restwidth * 0.33));
			}

		}

	};


} ();
