
var tx_wsmediaplayer_helper = {
		
	knownFileList : [],
	knownPlaylists : {},
	playlistFilecount : {},
	listPlayCount : {},
	
	initializers : {
		playlists : [],
		players : []
	},
	
	
	initAll : function() {
		
		for (playlistCount = 0; playlistCount < tx_wsmediaplayer_helper.initializers.playlists.length; playlistCount++) {
			var data = tx_wsmediaplayer_helper.initializers.playlists[playlistCount];
			tx_wsmediaplayer_helper.registerPlaylist.call(tx_wsmediaplayer_helper, data[0], data[1]);
		}
		
		for (playCount = 0; playCount < tx_wsmediaplayer_helper.initializers.players.length; playCount++) {
			tx_wsmediaplayer_helper.initializers.players[playCount].call();
		}
		
	},
	
	
	getContext : function() {
		return jQuery(this.container).parents(".tx-wsmediaplayer-pi1:first").data("wsPlayerContext");
	},
	

	
	registerPlaylist : function(playerID, playlistID) {
		
		this.listPlayCount[playlistID] = 0;
		
		if (!playerID) {
			var p = jQuery("#" + playlistID);
			var foundPlayer = false;
			var iterations = 0;
			var tPl;
			while (!foundPlayer) {
				iterations++;
				p = p.parent();
				tPl = p.find(".tx-wsmediaplayer-pi1:first");
				if (tPl.length) {
					var playerID = tPl.parent().attr("id").replace(/[^0-9]/g, '');
					foundPlayer = true;
					break;
				};
				if (iterations > 50) break;
			};
		}
		
		if (playerID) {
			if (typeof(this.knownPlaylists[playerID]) == "undefined") {
				this.knownPlaylists[playerID] = [playlistID];
			} else {
				this.knownPlaylists[playerID].push(playlistID);
			};
		} else {
			
			// No registered player, but this playlist still needs some onclick functionality.
			jQuery("#" + playlistID + " .playlistEntry")
				.hover(
					function() { jQuery(this).addClass("hover"); },
					function() { jQuery(this).removeClass("hover"); }
				)
				.click( function() {
					var func = new tx_wsmediaplayer();
					func.events.loadPlaylistEntry.call( this );
				});
			;
			
			//jQuery("#" + playlistID).addClass("noLinkToPlayer");
		};
		
	}
};


jQuery(document).ready( tx_wsmediaplayer_helper.initAll );




var tx_wsmediaplayer = function() {
	
	this.settings = {
		id : 0,
		jwParameters : {},
		preInitFunction : function(){},
		
		autostart : false,
		forcedVideoID : 0,
		defaultVideoID : 0,
		repeatMode : false,
		shuffleMode : false,
		hidePlaylist : false,
		hidePlaylistPermanently : false,
		apiURL : "",
		
		selectors : {
			playlistFrame : ".playlistFrame",
			playlistEntry : ".playlistEntry",
			playlistIDprefix : "playlistEntry_"
		}
	};
	
	this.currentPlaylist = false;
	this.forceStop = false;
	
	
	this.setID = function (id) {
		
		this.settings.id = id;
		
	};
	
	this.setJWPlayerSettings = function (settings) {
		
		this.settings.jwParameters = settings;
		
	};
	
	this.setPreInitFunction = function (preInitFunction) {
		
		this.settings.preInitFunction = preInitFunction;
		
	};
	
	this.resetAllPlaylistStatuses = function(leaveActiveState) {
		
		if (typeof(tx_wsmediaplayer_helper.knownPlaylists[this.settings.id]) != "undefined") {
			for (i = 0; i < tx_wsmediaplayer_helper.knownPlaylists[this.settings.id].length; i++) {
				var selection = jQuery("#" + tx_wsmediaplayer_helper.knownPlaylists[this.settings.id][i]).find(".active,.paused,.loading,.playing").not(".states *");
				if (!leaveActiveState) selection.removeClass("active paused loading playing");
				else selection.removeClass("paused loading playing");
			}
		}
		
	};
	
	this.events = {
		
		onPlay : function() {
			var controller = tx_wsmediaplayer_helper.getContext.call(this);
			
			if (controller.currentPlaylist) {
				jQuery("#" + controller.currentPlaylist + " .active").removeClass("paused loading").addClass("playing");
			};
		},
		
		
		onPause : function() {
			var controller = tx_wsmediaplayer_helper.getContext.call(this);
			
			if (controller.currentPlaylist) {
				jQuery("#" + controller.currentPlaylist + " .active").removeClass("playing loading").addClass("paused");
			};
		},
		
		
		onComplete : function() {
			var controller = tx_wsmediaplayer_helper.getContext.call(this);
			
			if (typeof(tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id]) != "undefined") {
				// If the playlist has been hidden, show it now.
				if (controller.settings.hidePlaylist && !controller.settings.hidePlaylistPermanently) {
					for (i = 0; i < tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id].length; i++) {
						jQuery("#" + tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id][i]).fadeIn();
					}
					controller.settings.hidePlaylist = false;
				};
				
				var selItem = jQuery("#" + controller.currentPlaylist + " " + " .active");
				controller.resetAllPlaylistStatuses(true);
				
				if (!controller.forceStop) {
					
					// In case no "playing from" has been set, get the first known playlist and attach to that.
					if (!controller.currentPlaylist && tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id].length) {
						controller.currentPlaylist = tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id][0];
					}
					
					// Find out what we should do next, based on the repeat-settings
					switch (controller.settings.repeatMode) {
						case "none":
							// Do not start another video - the user needs to do that himself.
							break;
						case "list":
							// If shuffle-mode is on, skip to random - otherwise just load the next video.
							if (controller.settings.shuffleMode) {
								// Jump to random, but not if the entire list has been played by now (that's what "true" does)
								controller.skipToRandomInPlaylist.call(controller, true);
							} else {
								controller.skipToNextInPlaylist.call(controller);
							};
							break;
						case "always":
							// If shuffle-mode is on, skip to random - otherwise just load the next video.
							if (controller.settings.shuffleMode) {
								controller.skipToRandomInPlaylist.call(controller);
							} else {
								controller.skipToNextInPlaylist.call(controller);
							};
							break;
						case "single":
							// Repeat the file that's already been played.
							controller.events.loadPlaylistEntry.call(selItem);
							break;
					};
				};
			}
		},
		
		
		onError : function() {
			var controller = tx_wsmediaplayer_helper.getContext.call(this);
		},
		
		
		onReady : function() {
			var controller = tx_wsmediaplayer_helper.getContext.call(this);
			
			if ((controller.settings.forcedVideoID || controller.settings.defaultVideoID) && controller.settings.autostart) {
				
				// Do stuff if "forcedVideoID" is set (meaning we need to force-load an entry, regardless of it being on the playlist or not)
				if (controller.settings.forcedVideoID) {
					
					// On the off-chance that the video is already in one of the playlists, try to mark it as playing
					// (it will already have been marked active by registerPlaylist())
					if (typeof(tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id]) != "undefined") {
						for (i = 0; i < tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id].length; i++) {
							var curItem = jQuery("#" + tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id][i] + ".active");
							curItem
								.removeClass("paused loading")
								.addClass("playing")
								.data("playCount", 1)
							;
						}
					}

					
					// Update play stats for the video we're about to play
					controller.updateStatsForUID(controller.settings.forcedVideoID);
				}
				
				// Tell the player to start playing.
				controller.getJW().play();
			}
			
			// If we're here, there wasn't any forced ID or default ID. However, autostart may still be
			// valid, in which case we load the first entry from the first playlist and just go at it!
			else if (controller.settings.autostart && (typeof(tx_wsmediaplayer_helper.knownPlaylists[controller.settings.id]) != "undefined")) {
				
				tx_wsmediaplayer.playingFrom = tx_wsmediaplayer_helper.knownPlaylists[0];
				
				// If shuffle-mode is on, play a random file - otherwise just play the first one.
				if (controller.settings.shuffleMode) {
					// Jump to random
					controller.skipToRandomInPlaylist();
				} else {
					controller.skipToNextInPlaylist();
				};
			
				
			};
			
		},
		
		
		loadPlaylistEntry : function() {
			var currentPlaylist = jQuery(this).parents(".playlistFrame:first");
			var controller = currentPlaylist.data("linkedPlayer");
			
			// Store ID of parent playlist
			var curID = currentPlaylist.attr("id");
			
			// Get some placeholders and stuff
			var entryHolder = jQuery(this);
			var uid = entryHolder.find(".uid").text();
			
			try {
				if (curID) controller.currentPlaylist = curID;
				controller.forceStop = false;
				
				// Update the play stats for this movie
				controller.updateStatsForUID.call(controller, uid);
				
				// Remove "active"-flag from all entries
				controller.resetAllPlaylistStatuses();
			} catch (e) {}
			
			// Update internal play-count, so we know how many times this video has been played.
			var newPlaycount = parseInt(entryHolder.data("playCount")) + 1;
			if (isNaN(newPlaycount)) newPlaycount = 1;
			entryHolder.addClass("active loading").data("playCount", newPlaycount);
			
			// Now, deal with the entry itself. Its data is already stored... if it's a string, 
			// it must be a location; otherwise we'll consider it to be a playlist entry for the player.
			if (typeof( tx_wsmediaplayer_helper.knownFileList[uid] ) == "string") {
				window.location = tx_wsmediaplayer_helper.knownFileList[uid];
			} else {
				try {
					controller.getJW().stop().load( tx_wsmediaplayer_helper.knownFileList[uid] ).play(true);
				} catch (e) {};
			};
		}
		
	};
	
	
	this.skipToNextInPlaylist = function () {
		if (tx_wsmediaplayer_helper.playlistFilecount[this.currentPlaylist]) {
			
			// Find previously selected entry, if any.
			var sel = jQuery("#" + this.currentPlaylist + " .active");
			var nextVideo = "";
			if (sel.length) {
				// A video is already active - get the entry after it.
				nextVideo = sel.next();
				
				if (!nextVideo.length) {
					// No video was selected - we must be at the end of the list. Will the repeat-settings allow us to start from the top?
					if (this.settings.repeatMode == "always") {
						// Start over.
						nextVideo = jQuery("#" + this.currentPlaylist + " " + " " + this.settings.selectors.playlistEntry + ":first");
					};
				};
			} else {
				// No video is active, so we'll start from the top.
				nextVideo = jQuery("#" + this.currentPlaylist + " " + " " + this.settings.selectors.playlistEntry + ":first");
			};
			
			if (nextVideo.length) {
				this.events.loadPlaylistEntry.call( nextVideo );
			};
			
		};
		
	};
	
	this.skipToRandomInPlaylist = function (doNotStartNewListIteration) {
		
		var allowedEntries = [];
		
		// Get all playlist entries.
		var selection = jQuery("#" + this.currentPlaylist + " " + " " + this.settings.selectors.playlistEntry ); // + ":visible");
		
		var p = this;
		
		// First, run through all the entries in the playlist.
		selection.each(function(){
			
			// Allow only entries that haven't been played in this iteration yet.
			var curPC = parseInt(jQuery(this).data("playCount"));
			if (isNaN(curPC)) curPC = 0;
			if (curPC < tx_wsmediaplayer_helper.listPlayCount[p.currentPlaylist]) {
				allowedEntries.push(this);
			};
			
		});
		
		// Now, are there any entries for us to play?
		if (allowedEntries.length) {
			// Yes - so pick one at random and play it, oh yeah!
			var selectedEntry = Math.floor(Math.random() * allowedEntries.length);
			this.events.loadPlaylistEntry.call( allowedEntries[selectedEntry] );
		} else {
			
			// All entries have been played an equal amount of times. Should we start another iteration?
			if (!doNotStartNewListIteration) {
				tx_wsmediaplayer_helper.listPlayCount[this.currentPlaylist]++;
				
				// Pick a video at random and play it.
				var selectedEntry = Math.floor(Math.random() * selection.length);
				this.events.loadPlaylistEntry.call( selection.eq(selectedEntry) );
				
			} else {
				
				tx_wsmediaplayer_helper.listPlayCount[this.currentPlaylist]++;
				
				// Remove all flags from all entries
				this.resetAllPlaylistStatuses();
				
				// Unload current file.
				this.getJW().stop()
				
			};
			
		};
		
		
	},
	
	
	
	
	this.updateStatsForUID = function(uid) {
		
		// Phone home and tell the backend that a video has been played.
		if (this.settings.apiURL) {
			jQuery.ajax({
				url : this.settings.apiURL,
				data : { uid : uid }
			});
		};
		
	},
	
	
	this.getJW = function() {
		return jwplayer("wsPlayer_" + this.settings.id);
	};
	
	this.setContext = function() {
		jQuery("#wsPlayer_" + this.settings.id).parents(".tx-wsmediaplayer-pi1:first").data("wsPlayerContext", this);
	};
	
	
	this.initialize = function () {
		
		this.settings.preInitFunction.call(this);
		this.setContext();
		
		var jw = this.getJW();
		
		jw.setup(this.settings.jwParameters);
		
		jw.onPlay ( this.events.onPlay );
		jw.onPause ( this.events.onPause );
		jw.onComplete ( this.events.onComplete );
		jw.onError ( this.events.onError );
		jw.onReady ( this.events.onReady );
		
		// Run through all known playlists, and set relational info on those lists that are linked
		// to this specific player
		if (typeof(tx_wsmediaplayer_helper.knownPlaylists[this.settings.id]) != "undefined") {
			for (i = 0; i < tx_wsmediaplayer_helper.knownPlaylists[this.settings.id].length; i++) {
				var obj = jQuery("#" + tx_wsmediaplayer_helper.knownPlaylists[this.settings.id][i]);
				obj.data("linkedPlayer", this);
				
				// If the player config calls for hiding the playlist(s), do so now.
				if (this.settings.hidePlaylist || this.settings.hidePlaylistPermanently) obj.hide();
				
				// Set event handlers for the playlist entries
				obj.find(this.settings.selectors.playlistEntry)
					.hover(
						function() { jQuery(this).addClass("hover"); },
						function() { jQuery(this).removeClass("hover"); }
					)
					.click( this.events.loadPlaylistEntry )
				;
				
				// If "forcedVideoID" is set, we need to force-load a video entry from the database. In case that video is
				// already in the playlist, mark it as being active.
				if (this.settings.forcedVideoID) {
					var selAct = obj.find("*[class*='" + this.settings.selectors.playlistIDprefix + this.settings.forcedVideoID + "_']");
					if (selAct.length && !this.currentPlaylist) {
						selAct.addClass("active");
						this.currentPlaylist = tx_wsmediaplayer_helper.knownPlaylists[this.settings.id][i];
					}
				};
				
				// Store the amount of videos in the playlist.
				tx_wsmediaplayer_helper.playlistFilecount[ tx_wsmediaplayer_helper.knownPlaylists[this.settings.id][i] ] = obj.find(this.settings.selectors.playlistEntry).length;
			};
		};
		
	};
	
	
};
