var isIE = (/MSIE/.test(navigator.userAgent));
var isIE6 = (isIE && parseFloat(navigator.appVersion) == 4 && !(/MSIE\s7.0/.test(navigator.appVersion)) && !(/MSIE\s8.0/.test(navigator.appVersion)));
var isIE7 = (isIE && parseFloat(navigator.appVersion) == 4 && (/MSIE\s7.0/.test(navigator.appVersion)));
var isIE8 = (isIE && parseFloat(navigator.appVersion) == 4 && (/MSIE\s8.0/.test(navigator.appVersion)));
var isSafari = (/Safari/.test(navigator.userAgent));
var isChrome = (/chrome/.test(navigator.userAgent.toLowerCase()));

// depends on style!
// used to calculate dimentions of elements
var PLAYLIST_ELEMENT_OPEN_WIDTH = 176;
var PLAYLIST_ELEMENT_CLOSED_WIDTH = 22;

var PLAYLIST_OFFSET_TOP_BOTTOM = 64;
var PLAYLIST_ITEMSCONTAINER_OFFSET_TOP_BOTTOM = 81;

var PLAYER_MIDBUTTONS_HEIGHT = 44;
var PLAYER_HEADER_HEIGHT = 36;

var PLAYER_URL_HEIGHT = 26;

var INFO_PANEL_RESIZER_OFFSET_HEIGHT = 24;

var URL_INPUT_LEFT_RIGHT = 304;

var PLAYER_MIN_WIDTH = 635;
var PLAYER_MIN_HEIGHT = 340;

function Movie(movieName) {
    if(navigator.appName.indexOf("Microsoft") != -1) {
		return window[movieName+"_flashobject"];
	} else {
		return document[movieName+"_flashobject"];
	}
};

function windowHeight () {
	return (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight);
}

function windowWidth () {
	return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth);
}
function myParseInt (a) {
	return 1 * a;
}

var PlaylistItem = Class.create ();
PlaylistItem.prototype = {
	type: 'playlistItem',
	initialize: function (playlist, jsonObj, insertBefore) {
		Object.extend(this, TemplatedElement);
		this.playlist = playlist;
		this.jsonObj = jsonObj;

		this._buildFromTemplate('template_playlist_item');

		if (arguments.length == 2)
			this.playlist.itemsContainer.appendChild(this.element);
		else
			this.playlist.itemsContainer.insertBefore(this.element, insertBefore);

		this.thumbnail.src = this.jsonObj.thumbnail_url;

		if (this.jsonObj.ytdeleted) {
			Element.addClassName (this.element, 'deleted');
		} else if (this.jsonObj.isprivate) {
			Element.addClassName (this.element, 'private');
		}

		//hint
		this.hintText =
			//jsonObj.description + '<br /><br />' +
			'<div class="t">' + jsonObj.title + '</div>' +
			'<div><span class="lb">Length: </span>' + jsonObj.length_seconds + '</div>' +
			'<div><span class="lb">Played: </span>' + formatCommasInt(jsonObj.view_count) + ' times</div>' +
			'<div><span class="lb">Rating: </span>' + jsonObj.rating_avg + '</div>' +
			'<div><span class="lb">Votes: </span>' + formatCommasInt(jsonObj.rating_count) + '</div>';

		// the drag
		dnd.registerDrop(this);
		if (isIE) {
			Event.stopObservingAll (this.element, "mouseout");
			this.element.onmouseout = this.hideHint.bindAsEventListener(this);
		}
	},

	showHint: function (event) {
		var p = Position.cumulativeOffset(this.element);
		p[1] -= this.playlist.itemsContainer.scrollTop;
		if (p[0] + this.element.offsetWidth < windowWidth() - 100) {
			$('playlist_item_hint').style.top = p[1] + 'px';
			$('playlist_item_hint').style.left = p[0] + this.element.offsetWidth + 'px';
			$('playlist_item_hint').innerHTML = this.hintText;
			$('playlist_item_hint').style.display = 'block';
			$('playlist_item_hint').style.width = '';
		} else {
			$('playlist_item_hint').style.top = p[1] + this.element.offsetHeight + 'px';
			$('playlist_item_hint').style.left = p[0] - 10 + 'px';
			$('playlist_item_hint').style.width = this.element.offsetWidth + 20 + 'px';
			$('playlist_item_hint').innerHTML = this.hintText;
			$('playlist_item_hint').style.display = 'block';
		}
		Element.addClassName (this.element, 'hovered');
	},

	hideHint: function (event) {
		$('playlist_item_hint').style.display = 'none';
		Element.removeClassName (this.element, 'hovered');
	},

	click: function (event) {
		this.dblclick(event);
	},

	dblclick: function (event) {
		var myind = this.playlist.indexOfItem(this);
		if (myind > -1) {
			this.playlist.selectItem(myind);
			this.playlist.playSelected();
		}
	},

	hover: function (event) {
		Element.addClassName (this.element, 'playlist_item_hover');
		this.element_oper.style.display = 'block';
		this.element_oper2.style.display = 'block';
		Event.stop(event);
	},

	unhover: function (event) {
		Element.removeClassName (this.element, 'playlist_item_hover');
		this.element_oper.style.display = 'none';
		this.element_oper2.style.display = 'none';
		Event.stop(event);
	},

	select: function () {
		Element.addClassName (this.element, 'playlist_item_selected');
	},

	deselect: function () {
		Element.removeClassName (this.element, 'playlist_item_selected');
	},

	removeClick: function () {
		this.playlist.removeFromPlaylist(this.playlist.indexOfItem(this));
	},

	remove: function () {
		this.hideHint();
		this.playlist.itemsContainer.removeChild(this.element);
	},

	downloadConverted: function () {
		Converter.downloadConverted (this.jsonObj);
	},

	downloadFlv: function () {
		Converter.downloadFLV(this.jsonObj);
	},

	recommend: function (event) {
		send_recommendation(this.jsonObj.id, this.jsonObj.title);
	},


	/////////

	moveUp: function (event) {
		this.playlist.reorderVideo(this, 'up');
		Event.stop(event);
	},
	moveDown: function (event) {
		this.playlist.reorderVideo(this, 'down');
		Event.stop(event);
	},
	placeElementBefore: function (item) {
		this.playlist.itemsContainer.removeChild(this.element);
		this.playlist.itemsContainer.insertBefore(this.element, item.element);
	},

	startDrag: function(event) {
		/*if (Event.element(event) != this.thumbnail &&
			Event.element(event) != this.fakeHoverable) return;*/
		dnd.startDragging(event, this, this.draggedSuccess.bind(this));
		dnd.setImage(this.jsonObj.thumbnail_url);
	},

	draggedSuccess: function (dragObj, dropTarget) {
		if (dropTarget == this) return true;
		if (dropTarget.type == 'playlist' || dropTarget.type == 'playlistItem') {
			// the problem is that indexOfItem may pick the wrong video because it searches over jsonObj.id
			// that's why we search manually
			for (var i = 0; i < this.playlist.items.length; i ++)
				if (this.playlist.items[i] == this) {
					this.playlist.removeFromPlaylist(i);
					break;
				}
			//this.playlist.removeFromPlaylist(this.playlist.indexOfItem(this));
		}
	},

	dragHover: function(event, draggedObject) {
		if (draggedObject == this) return;
		dnd.setText('add to playlist here...');
		var ovrl = dnd.getOverlap(event, 'vertical');
		var nid = '';
		if (ovrl >= 0.5)
			nid = 'before';
		else
			nid = 'after';
		if (this.insertDirection != nid)
			this.dragUnhover();
		else
			return;
		this.dragInsertDirection = nid;
		Element.addClassName(this.element, 'playlist_item_drag_' + this.dragInsertDirection);
	},

	dragUnhover: function() {
		Element.removeClassName(this.element, 'playlist_item_drag_' + this.dragInsertDirection);
	},

	recieveDrag: function (draggedObject) {
		Element.removeClassName(this.element, 'playlist_item_drag_' + this.dragInsertDirection);
		if (draggedObject == this) return true;
		// bug: the player checks if the video exists in the current playlist. BUT this does not allow the user
		// to reorder items. So we have to check here if the video comes from the same playlist and if so -
		// skip check in player
		var skipCheck = false;
		if (draggedObject.type == 'playlistItem')
			if (draggedObject.playlist == this.playlist)
				var skipCheck = true;
		if (draggedObject.type == 'saved_playlist') {
			if (this.dragInsertDirection == 'before')
				this.playlist.addToPlaylistMultiple(draggedObject.jsonObj.videos, this, 'before');
			else
				this.playlist.addToPlaylistMultiple(draggedObject.jsonObj.videos, this, 'after');
		} else {
			if (this.dragInsertDirection == 'before')
				this.playlist.addToPlaylist(draggedObject.jsonObj, this, 'before', skipCheck);
			else
				this.playlist.addToPlaylist(draggedObject.jsonObj, this, 'after', skipCheck);
		}
	}
};

var Playlist = Class.create();
Playlist.prototype = {
	type: 'playlist', //for recognizing during drag

	initialize: function (player, visible) {
		Object.extend(this, TemplatedElement);
		if (arguments.length == 1)
			this.visible = true;
		else
			this.visible = visible;

		this.player = player;
		this.container = player.playlist_element;
		this._buildFromTemplate('template_playlist');
		this.container.appendChild(this.element);

		this._onEndScrolling = this.onEndScrolling.bindAsEventListener(this);
		this._onScrollTimer = this.onScrollTimer.bind(this);

		if (this.visible)
			this.showPlaylist();
		else
			this.hidePlaylist();

		this.items = new Array ();
		this.current_selected = -1; // index !!!
		this.current_playing = -1; // index !!!
		this.shuffle = false;
		this.repeat = 0; // 0 - none, 1 - all playlist

		this.shown_once = false;

		dnd.registerDrop(this);

		this.allowPlaylistSave = false;

		this.loadedPlaylistName = '';
		this.loadedPlaylistId = null;
		this.loadedPlaylistDescription = '';
		this.playlistModified = false;

		Event.observe (this.itemsContainer, "mousewheel", this.onMouseWheel.bindAsEventListener(this));
		this.updatePlaylistMenuButton();

		this.rebuildShuffleList();// won't do anything here really, but just in case
	},

	getVideosJsonArr: function () {
		var res = new Array();
		for (var i = 0; i < this.items.length; i ++)
			res.push(this.items[i].jsonObj);
		return res;
	},

	changeRepeat: function () {
		this.repeat = 1 - this.repeat;
		/*this.img_repeat.src = PLAYER_REPEAT_1 + this.repeat + '.gif';
		switch (this.repeat) {
			case 0:	this.img_repeat.title = 'Repeat mode: no repeat';break;
			case 1: this.img_repeat.title = 'Repeat mode: all playlist';break;
			//case 2: this.img_repeat.title = 'Repeat mode: current video';break;
		}
		this.img_repeat.alt = this.img_repeat.title;*/
		this.btnRepeat.innerHTML = 'Repeat is ' + (this.repeat ? 'on' : 'off');
		this.hidePlaylistMenu();
		this.updateFlashObject();
	},

	changeShuffle: function () {
		this.shuffle = !this.shuffle;
		this.btnShuffle.innerHTML = 'Shuffle is ' + (this.shuffle ? 'on' : 'off');
		if (this.shuffle)
			this.rebuildShuffleList();// won't do anything here really...
		this.hidePlaylistMenu();
		this.updateFlashObject();
	},

	showPlaylist: function () {
		this.visible = true;
		this.shown_once = true;
		Element.removeClassName(this.player.element, 'closedPlaylist');
		this.player.updateSizes();
		this.hidePlaylistMenu();
	},

	hidePlaylist: function () {
		this.hidePlaylistMenu();
		this.visible = false;
		Element.addClassName(this.player.element, 'closedPlaylist');
		this.player.updateSizes();
	},

	showEmptyPlaylistMessage: function() {
		this.emptyPlaylistMessage.style.display = 'block';
	},
	hideEmptyPlaylistMessage: function() {
		this.emptyPlaylistMessage.style.display = 'none';
	},

	indexOfItem:function (item) {
		var i = 0;
		while (i < this.items.length) {
			if (this.items[i].jsonObj.id == item.jsonObj.id) return i;
			i ++;
		}
		return -1;
	},

	addToPlaylist: function (jsonObj, nextToItem, direction, skipCheckForDuplicate) {
		if (arguments.length == 3)
			var skipCheckForDuplicate = false;
		// if item exists - just select it
		if (!skipCheckForDuplicate)
			for (var i = 0; i < this.items.length; i ++) {
				if (this.items[i].jsonObj.id == jsonObj.id) {
					this.selectItem(i);
					alert ('This video already exists in the playlist!');
					return;
				}
			}
		this.hideEmptyPlaylistMessage();
		if (arguments.length == 1 || typeof(nextToItem) == "undefined") { //simply adding
			var n = new PlaylistItem(this, jsonObj);
			this.items.push (n);
			this.addToShuffleList(this.items.length - 1);
			this.selectItem(this.items.length - 1);
			if (this.items.length == 2 && !this.shown_once)
				this.showPlaylist();
		} else { //adding by dragging
			var z = this.indexOfItem(nextToItem); //detect the index of the element recieved the drag
			if (z==null) return;
			if (direction == 'before') { //inseting before
				var n = new PlaylistItem(this, jsonObj, nextToItem.element);
				this.items.splice(z,0,n);
				this.addToShuffleList(z);
				this.selectItem(z);
			} else { //inserting after
				if (z == this.items.length - 1) { //inserting after the last element - like normal adding
					var n = new PlaylistItem(this, jsonObj);
					this.items.push (n);
					this.addToShuffleList(this.items.length - 1);
					this.selectItem(this.items.length - 1);
				} else { // inserting after
					nextToItem = this.items[z+1];
					var n = new PlaylistItem(this, jsonObj, nextToItem.element);
					this.items.splice(z+1,0,n);
					this.addToShuffleList(z+1);
					this.selectItem(z);
				}
			}
		}
		this.playlistModified = true;
		this.updatePlaylistMenuButton();
		this.updateScrollbar();
		this.updateFlashObject();
		IEForceRedraw();
	},

	addToPlaylistMultiple: function (jsonArr, nextToItem, direction) {
		var i = 0;
		if (nextToItem == 'load_playlist') {
			for (i = 0; i < jsonArr.length; i ++)
				this.addToPlaylist(jsonArr[i]);
		} else if (direction == 'after') {
			for (i = jsonArr.length - 1; i >=0; i --)
				this.addToPlaylist(jsonArr[i], nextToItem, direction, true);
		} else {
			for (i = 0; i < jsonArr.length; i ++)
				this.addToPlaylist(jsonArr[i], nextToItem, direction, true);
		}
		this.updateScrollbar();
	},

	reorderVideo: function (index, direction) {
		if (typeof(index) != "number")
			var index = this.indexOfItem(index);
		if (!this.items[index]) return null;
		if (direction == 'up' && index == 0) return;
		if (direction == 'down' && index == this.items.length - 1) return;
		if (direction == 'down') {
			direction = 'up'; index = index + 1;
		} // so - we are moving video items[index] upstairs
		var vid = this.items[index];
		this.items = this.items.without(this.items[index]);
		vid.placeElementBefore(this.items[index-1]);
		this.items.splice(index-1, 0, vid);
		this.playlistModified = true;
		this.updatePlaylistMenuButton();
	},

	removeFromPlaylist: function (index) {
		this.items[index].remove();
		this.items = this.items.without (this.items[index]);
		this.updateScrollbar();
		this.updateFlashObject();
		this.playlistModified = true;
		this.updatePlaylistMenuButton();
		this.removeFromShuffleList(index);
		if (this.items.length == 0)
			this.showEmptyPlaylistMessage();
	},

	removeCurrentFromPlaylist: function () {
		this.playlistModified = true;
		this.updatePlaylistMenuButton();
		if (this.current_selected > -1)
			this.removeFropPlaylist(this.current_selected);
	},

	clearPlaylist: function () {
		this.hidePlaylistMenu();
		for (var i = this.items.length-1; i >= 0; i--)
			this.removeFromPlaylist(i);
	},

	addAllToFavorites: function () {
		if (!logged_in)
			showLoginOrRegisterForm();
		else {
			for (var i = this.items.length - 1; i >= 0; i --)
				Favorites.addVideo (this.items[i].jsonObj, false);
			if (this.items.length > 0)
				alert ('The videos were added to your favorites');
		}
	},

	savePlaylist: function () {
		this.hidePlaylistMenu();
		if (!this.playlistModified) return;
		if (!logged_in) {
			//alert ("You have to register or log in to have access to this feature");
			showLoginOrRegisterForm();
		} else if (this.items.length == 0) {
			alert ("Please, add some videos to the playlist first!");
		} else {
			if (this.loadedPlaylistId)
				SavedPlaylists.saveFromPlayer(this, this.onPlaylistSaved.bind(this));
			else
				this.savePlaylistAs();
		}
	},
	savePlaylistAs: function () {
		this.hidePlaylistMenu();
		if (!logged_in) {
			//alert ("You have to register or log in to have access to this feature");
			showLoginOrRegisterForm();
		} else if (this.items.length == 0) {
			alert ("Please, add some videos to the playlist first!");
		} else {
			SavedPlaylists.saveFromPlayerAs(this, this.onPlaylistSaved.bind(this));
		}
	},
	onPlaylistSaved: function (id, name, description) {
		this.loadedPlaylistName = name;
		this.loadedPlaylistId = id;
		this.loadedPlaylistDescription = description;
		this.playlistModified = false;
		this.updatePlaylistMenuButton();
	},

	appentPlaylistTo: function () {
		if (!logged_in) {
			showLoginOrRegisterForm();
		} else if (this.items.length == 0) {
			alert ("Please, add some videos to the playlist first!");
		} else {
			SavedPlaylistSelect.openBox (this.onAppentPlaylistToOK.bind(this));
		}
	},

	onAppentPlaylistToOK: function (id) {
		var pl = SavedPlaylists.getListObjectById(id);
		if (pl) {
			SavedPlaylistSelect.showLoading();
			pl.appendVideos(this.getVideosJsonArr(), this.onFinishedAppendingToPlaylist.bind(this));
		}
	},
	onFinishedAppendingToPlaylist: function () {
		SavedPlaylistSelect.closeBox();
	},

	updatePlaylistMenuButton: function () {
		if (this.player.standalone) return;
		var name = '';
		if (this.loadedPlaylistId)
			name = this.loadedPlaylistName;
		else
			name = 'Untitled playlist';
		this.currentPlaylistName.title = name;

		if (name.length > 18) name = name.substring(0, 15) + '...';

		this.currentPlaylistName.innerHTML = name;

		if (this.playlistModified) {
			this.currentPlaylistName.innerHTML += ' *';
			this.currentPlaylistName.title += ' (modified)';
		}
	},

	selectItem: function (index) {
		if (index == this.current_selected) return;
		if (this.current_selected > -1 && this.current_selected < this.items.length)
			this.items[this.current_selected].deselect();
		if (index > -1) {
			this.current_selected = index;
			this.items[this.current_selected].select();
		}
	},

	playSelected: function () {
		if (this.current_selected > -1) {
			this.currentShuffleIndex = this.shuffledList.indexOf(this.current_selected);
			this.currentPlaying = this.items[this.current_selected];
			this.player.loadVideo(this.items[this.current_selected].jsonObj);
			this.updateFlashObject();
		}
	},

	clickPlayNext: function () {
		this.currentPlayingIsOver();
	},

	clickPlayPrev: function () {
		if (this.shuffle) {
			this.playPrevRandom();
			return;
		}
		if (this.repeat == 1) this.playPrev(true);
		if (this.repeat == 0) this.playPrev(false)
	},

	currentPlayingIsOver: function() {
		if (this.shuffle) {
			this.playNextRandom();
			return;
		}
		if (this.repeat == 1) this.playNext(true);
		if (this.repeat == 0) this.playNext(false)
	},

	playNext: function (restartIfLast) {
		if (arguments.length < 1) var restartIfLast = true;
		//we don't know what is the index of the current plaing video in this.itemas array - if we keep it, it may have changed!
		if (this.items.length == 0) return;
		var i = this.indexOfItem(this.currentPlaying);
		i++;
		if (!restartIfLast && i >= this.items.length) return;
		if (i >= this.items.length) i = 0;
		this.currentPlaying = this.items[i];
		this.selectItem(i);
		this.player.loadVideo(this.items[i].jsonObj);
		this.updateFlashObject();
	},

	playPrev: function (restartIfFirst) {
		if (arguments.length < 1) var restartIfFirst = true;
		//we don't know what is the index of the current plaing video in this.itemas array - if we keep it, it may have changed!
		if (this.items.length == 0) return;
		var i = this.indexOfItem(this.currentPlaying);
		i--;
		if (!restartIfFirst && i < 0) return;
		if (i < 0) i = this.items.length-1;
		this.currentPlaying = this.items[i];
		this.selectItem(i);
		this.player.loadVideo(this.items[i].jsonObj);
		this.updateFlashObject();
	},

	playNextRandom: function () {
		if (this.items.length == 0) return;
		if (this.items.length == 1) {
			this.player.restartCurrentVideo();
			return;
		}
		/*var i = this.indexOfItem(this.currentPlaying);
		z = i;
		while (z == i)
			z = Math.floor(Math.random() * this.items.length);
		this.currentPlaying = this.items[z];
		this.selectItem(z);
		this.player.loadVideo(this.items[z].jsonObj);
		this.updateFlashObject();*/
		var z = this.getNextShuffledIndex();
		if (z === false) return;
		this.currentPlaying = this.items[z];
		this.selectItem(z);
		this.player.loadVideo(this.items[z].jsonObj);
		this.updateFlashObject();
	},

	playPrevRandom: function () {
		if (this.items.length == 0) return;
		if (this.items.length == 1) {
			this.player.restartCurrentVideo();
			return;
		}
		var z = this.getPrevShuffledIndex();
		if (z === false) return;
		this.currentPlaying = this.items[z];
		this.selectItem(z);
		this.player.loadVideo(this.items[z].jsonObj);
		this.updateFlashObject();
	},

	/////////

	dragHover: function(event, draggedObject) {
		dnd.setText('add to playlist...');
		Element.addClassName(this.element, 'playlist_item_drag');
	},

	dragUnhover: function() {
		Element.removeClassName(this.element, 'playlist_item_drag');
	},

	recieveDrag: function (draggedObject) {
		Element.removeClassName(this.element, 'playlist_item_drag');
		if (draggedObject.type == 'saved_playlist')
			this.addToPlaylistMultiple(draggedObject.jsonObj.videos, this.items[this.items.length-1], 'after')
		else {
			if (draggedObject.type == 'playlistItem' && draggedObject.playlist == this )
				this.addToPlaylist(draggedObject.jsonObj, this.items[this.items.length-1], "after", true);
			else
				this.addToPlaylist(draggedObject.jsonObj);
		}
	},

	userHasLoggedIn: function () {
	},
	userHasLoggedOut: function () {
	},

	resize : function (height) {
		this.updateScrollbar();

		if (arguments.length == 0)
			var height = this.player.height - PLAYLIST_OFFSET_TOP_BOTTOM;
		height -= PLAYLIST_ITEMSCONTAINER_OFFSET_TOP_BOTTOM;
		this.itemsContainer.style.height = height + "px";
	},

	hidePlaylistMenu: function () {
		if (this.playlistMenuVisible)
			this.showhidePlaylistMenu();
	},

	showhidePlaylistMenu: function (event) {
		if (this.playlistMenuVisible)
			this.playlistMenuDropdown.style.display = 'none';
		else
			this.playlistMenuDropdown.style.display = 'block';
		this.playlistMenuVisible = !this.playlistMenuVisible;
	},

/* scrolling shits */
	updateScrollbar: function () {
		if (this.itemsContainer.scrollTop + this.itemsContainer.offsetHeight > this.itemsContainer.scrollHeight)
			this.itemsContainer.scrollTop = this.itemsContainer.scrollHeight - this.itemsContainer.offsetHeight;
	},

	scrollStep: 20,
	scrollFirstTimeout:350,
	scrollRepeatTimeout: 50,

	onMouseWheel: function (event) {
		var d = Event.wheelDelta (event);
		if (d == 0) return true;
		if (d > 0)
			this.itemsContainer.scrollTop -= this.scrollStep;
		else
			this.itemsContainer.scrollTop += this.scrollStep;
		return true;
	},

	scrollUp: function () {
		if (this._scrolling) {
			this.onEndScrolling();
			return;
		}
		if (this.itemsContainer.scrollTop <= 0)
			return;
		this._scrollDirection = 'up';
		this._scrolling = true;

		this.itemsContainer.scrollTop -= this.scrollStep;

		Event.observe (document, 'mouseup', this._onEndScrolling);
		setTimeout(this._onScrollTimer, this.scrollFirstTimeout);
	},
	scrollDown: function () {
		if (this._scrolling) {
			this.onEndScrolling();
			return;
		}
		if (this.itemsContainer.scrollTop >= this.itemsContainer.scrollHeight - this.itemsContainer.offsetHeight)
			return;
		this._scrollDirection = 'down';
		this._scrolling = true;
		this._maxScrollTop = this.itemsContainer.scrollHeight - this.itemsContainer.offsetHeight;

		this.itemsContainer.scrollTop += this.scrollStep;

		Event.observe (document, 'mouseup', this._onEndScrolling);
		setTimeout(this._onScrollTimer, this.scrollFirstTimeout);
	},
	onScrollTimer: function () {
		if (!this._scrolling) return;
		if (this._scrollDirection == 'up') {
			if (this.itemsContainer.scrollTop > 0)
				this.itemsContainer.scrollTop = Math.max(this.itemsContainer.scrollTop - this.scrollStep, 0);
		} else {
			if (this.itemsContainer.scrollTop < this._maxScrollTop)
				this.itemsContainer.scrollTop = Math.min(this._maxScrollTop, this.itemsContainer.scrollTop + this.scrollStep);
		}
		setTimeout (this._onScrollTimer, this.scrollRepeatTimeout);
	},
	onEndScrolling: function () {
		this._scrolling = false;
		this._scrollDirection = '';
		Event.stopObserving (document, 'mouseup', this._onEndScrolling);
	},
/* end scrolling shits */
	get_prev_next_status: function () {
		if (this.items.length < 2)
			return 0;
		if (this.repeat)
			return 3;
		if (!this.currentPlaying)
			return 2;
		else {
			if (this.shuffle)
				var i = this.currentShuffleIndex;
			else
				var i = this.indexOfItem(this.currentPlaying);

			if (i > 0 && i < this.items.length - 1) // show both buttons
				return 3
			else
			if ( i == this.items.length - 1) // it's last in playlist
				return 1
			else // it's first in playlist OR IS REMOVED FROM PLAYLIST
				return 2;
		}
	},
	updateFlashObject: function () {
		var m = Movie(this.player.flashObjectElement.id);
		if (!m || !m.sendPlaylistEvent) return;
		m.sendPlaylistEvent(this.get_prev_next_status());
	},
	embed: function () {
		if (this.items.length > 0) {
			this.hidePlaylistMenu();
			if (this.loadedPlaylistId && !this.playlistModified)
				EmbedPlayer.open (EmbedPlayer.EMBED_SAVED_LIST, {id: this.loadedPlaylistId, name: this.loadedPlaylistName});
			else
				EmbedPlayer.open (EmbedPlayer.EMBED_RUNTIME_LIST, this.getVideosJsonArr());
		} else
			alert ('Please add some videos to the playlist first!');
	},

	addToShuffleList: function (real_index) {
		for (var i = 0, c = this.shuffledList.length; i < c; i ++)
			if (this.shuffledList[i] >= real_index) this.shuffledList[i] ++;
		// when we add, it should always be AFTER the current playing video's position in the shuffled list, if repeat is on
		// if we add BEFORE the current playing video, we must change the shuffled index too
		var a;
		if (this.repeat == 0)
			a = 1 + this.currentShuffleIndex + Math.round((this.shuffledList.length - this.currentShuffleIndex - 1) * Math.random());
		else {
			a = Math.round(this.shuffledList.length * Math.random()); // this.shuffle.length without -1 because we are adding one more element
			if (a <= this.currentShuffleIndex)
				this.currentShuffleIndex ++;
		}
		this.shuffledList.splice(a, 0, real_index);
	},
	removeFromShuffleList: function (real_index) {
		var a = this.shuffledList.indexOf (real_index);
		this.shuffledList.splice(a,1);
		for (var i = 0, c = this.shuffledList.length; i < c; i ++)
			if (this.shuffledList[i] > real_index) this.shuffledList[i] --;
		if (a <= this.currentShuffleIndex)
			this.currentShuffleIndex --;
	},
	rebuildShuffleList: function () {
		var cnt = this.items.length;
		if (cnt == 0) {
			this.shuffledList = [];
			this.currentShuffleIndex = 0;
			return;
		}
		if (cnt == 1) {
			this.shuffledList = [0];
			this.currentShuffleIndex = 0;
			return;
		}
		current_index = this.indexOfItem(this.currentPlaying);
		// the items array is constructed to be 0,1,...,cnt-1
		// the current playing video must be the first in the shuffled playlist, because it is .... current playing :)
		var items = [current_index];
		for (var i = 0; i < cnt; i ++)
			if (i != current_index)
				items.push(i);
		var tmp;
		// protect items[0] from participating in the shuffle
		for (var i = 1; i < cnt; i ++) {
			var ind = 1 + Math.round((cnt - 2) * Math.random());
			// swap items[i] and items[ind]
			// we aren't operating on large arrays so skip the no-middle-variable approach
			tmp = items[i];
			items[i] = items[ind];
			items[ind] = tmp;
		}


		this.shuffledList = items;
		this.currentShuffleIndex = 0;
	},
	getNextShuffledIndex: function () {
		if (this.items.length == 0) return false;
		if (this.currentShuffleIndex >= this.items.length - 1) {
			if (this.repeat == 0)
				return false;
			else
				this.currentShuffleIndex = 0;
		} else
			this.currentShuffleIndex ++;
		return this.shuffledList[this.currentShuffleIndex];
	},
	getPrevShuffledIndex: function () {
		if (this.items.length == 0) return false;
		if (this.currentShuffleIndex == 0) {
			if (this.repeat == 0)
				return false;
			else
				this.currentShuffleIndex = this.items.length - 1;
		} else
			this.currentShuffleIndex --;
		return this.shuffledList[this.currentShuffleIndex];
	}
};

var Player = Class.create();
Player.prototype = {
	type: 'player',
	width: 600,
	height: 500,
	infoPanelHeight: 120,
	infoVisible: true,
	_showPlaylist: false,
	_showInfo: false,
	noAutostart: false,
	standalone: false,
	initialize: function (players_container) {
		Object.extend(this, TemplatedElement);
		this._buildFromTemplate('template_player');
		this.b_c = players_container;
		this.b_c.element.appendChild(this.element);

		var ps = Cookies.getValue ('ps', '');
		if (ps != '') {
			var ch = ps.split(',');
			this.width = Math.max (parseInt(ch[0]), PLAYER_MIN_WIDTH);
			this.height = Math.max(parseInt(ch[1]), PLAYER_MIN_HEIGHT);
			this.elleft = Math.max (parseInt(ch[2]), 0);
			this.eltop = Math.max (parseInt(ch[3]), 0);
			this.infoPanelHeight = parseInt(ch[4]);
			if (ch[5] == 'true') this._showInfo = true;
			if (ch[6] == 'true') this._showPlaylist = true;
		}
		this.checkIfPlayerFits();

		this._endMoving   = this.endMoving.bindAsEventListener(this);
    	this._updateMoving = this.updateMoving.bindAsEventListener(this);
    	this._resizeEnd   = this.ResizeEnd.bindAsEventListener(this);
    	this._resizeUpdate = this.ResizeUpdate.bindAsEventListener(this);
    	this._resizePanelEnd   = this.resizeInfoPanelEnd.bindAsEventListener(this);
    	this._resizePanelUpdate = this.resizeInfoPanelUpdate.bindAsEventListener(this);

    	this.playlist = new Playlist(this);
    	if (!this._showPlaylist) this.playlist.hidePlaylist();

		this.flashObjectElement.id = 'player_td_' + this.b_c.getNextID();

		this.infoBox = new TTabbedBox(this.infoTabsContainer);
		this.infoBox.setHeight(this.infoPanelHeight);
		this.btnRelatedVideos = new TTabbedBoxButton(null, 'Related videos', this.showRelatedVideos.bind(this));
		this.btnMoreVideos = new TTabbedBoxButton(null, 'More videos', this.showUserVideos.bind(this));
		this.btnFavorites = new TTabbedBoxButton(null, 'Favorites', this.showUserFavorites.bind(this));
		this.infoBoxTabDescription = new  TTabbedBoxTab(null, 'Description', '');
		this.infoBoxTabComments = new TTabbedBoxTab (null, 'Comments <span class="count"></span> | <a href="" target="_blank" rel="nofolow" title="Show all comments">All</a>', '');
		this.infoBoxTabProfile = new TTabbedBoxTab (null, 'Profile', '');

		this.infoBox.appendTab(this.btnRelatedVideos);
		this.infoBox.appendTab(this.btnMoreVideos);
		this.infoBox.appendTab(this.btnFavorites);
		this.infoBox.appendTab(this.infoBoxTabDescription);
		this.infoBox.appendTab(this.infoBoxTabComments);
		this.infoBox.appendTab(this.infoBoxTabProfile);
		this.infoBox.showTab(3);

		this.spanCommentsCount = this.infoBoxTabComments.head.getElementsByTagName('span')[0];
		this.linkAllComments = this.infoBoxTabComments.head.getElementsByTagName('a')[0];

		this.setSize(this.width, this.height);
		if (this.elleft && this.eltop)
			this.setPosition(this.elleft, this.eltop);
		else
			this.centerPlayer();
		if (this._showInfo != this.infoVisible) this.showHideInfo();

		this.trayElement = Tray.addToTray();
		this.trayElement.trayItemReceieveDrag = this.playlist.recieveDrag.bind(this.playlist);

		this.ratingStar = new Array (this.ratingStar0, this.ratingStar1, this.ratingStar2, this.ratingStar3, this.ratingStar4, this.ratingStar5);

		IEForceRedraw();
		this.playlist.resize();
	},
	onWindowResize: function () {
		if (!this.checkIfPlayerFits()) {
			this.setPosition(this.elleft, this.eltop);
			this.setSize(this.width, this.height);
		}
	},

	checkIfPlayerFits: function () {
		var res = true;
		if (this.elleft < 0) {  this.elleft = 0; res = false; }
		if (this.eltop < 0)  {  this.eltop = 0;  res = false;  }
		var winwidth = windowWidth(), winheight = windowHeight();
		if (this.width + this.elleft > winwidth) {
			if (this.width < winwidth)
				this.elleft = winwidth - this.width; // stick it to the right
			else { // stick it to the left and make it full-width
				this.elleft = 0;
				this.width = winwidth;
			}
			res = false;
		}
		if (this.height + this.eltop > winheight) {
			if (this.height < winheight)
				this.eltop = winheight - this.height;
			else {
				this.eltop = 0;
				this.height = winheight;
			}
			res = false;
		}
		return res;
	},

	popout: function () {
		var newwin = window.open ('/player.php?plrid=' + this.plind + '&info=' + (this.infoVisible?'yes':'no') +
			'&pll=' + (this.playlist.visible?'yes':'no') + '&t=' + current_theme, 'player' + this.plind,
			'height=' + this.element.offsetHeight + ',width=' + this.element.offsetWidth +
			',left=' + (this.element.offsetLeft) + ',top=' + (this.element.offsetLeft) +
			',scrollbars=no,toolbar=no,menubar=no,status=no,resizable=yes,directories=no');
		this.pauseIfPlaying();
		if (window.focus) newwin.focus();
	},

	addToFavorites: function () {
		if (this.jsonObj)
			Favorites.addVideo(this.jsonObj);
	},

	switchFooterURL: function () {
		if (this._urlInputVisible) {
			Element.removeClassName (this.element, 'url_open');
			this._urlInputVisible = false;
		} else {
			Element.addClassName (this.element, 'url_open');
			this._urlInputVisible = true;
		}
		this.updateSizes();
	},

	click_input_URL: function () {
		this.URLinput.select();
	},

	embed: function () {
		if (!this.jsonObj) return;
		/*if (user_name)
			EmbedPlayer.open (EmbedPlayer.EMBED_SINGLE_VIDEO, [this.jsonObj], this);
		else*/
		EmbedPlayer.createSimpleEmbed (this.jsonObj);
	},

	showHidePlaylist: function () {
		if (this.playlist.visible)
			this.playlist.hidePlaylist();
		else
			this.playlist.showPlaylist();
		IEForceRedraw();
	},

	showHideInfo: function () {
		this.infoVisible = !this.infoVisible;
		if (this.infoVisible)
			Element.removeClassName(this.element, 'closedInfo');
		else
			Element.addClassName(this.element, 'closedInfo');
		this.updateSizes();
		IEForceRedraw();
	},

	pauseIfPlaying: function () {
		if (this.minimized && !this.b_c.pauseOnMinimize) return false;
		if (this.pu_state > 0 && Movie (this.flashObjectElement.id).sendEvent) {
			Movie (this.flashObjectElement.id).sendEvent('playpause', 0, 0);
			return true;
		}
		return false;
	},
	playIfPaused: function () {
		if (this.pu_state == 0 && Movie (this.flashObjectElement.id).sendEvent) {
			Movie (this.flashObjectElement.id).sendEvent('playpause', 0, 0);
			return true;
		}
		return false;
	},

	minimize: function (event) {
		Event.stop(event);
		this.element.style.visibility = 'hidden';
		this.minimized = true;
		if (this.b_c.pauseOnMinimize) this.pauseIfPlaying();
	},
	onClickMinimize: function (event) {this.minimize(event) },

	onClickMaximize: function () {
		if (this.maximized)
			this.restore();
		else
			this.maximize();
	},

	onClickShrink: function () {
		if (this.shrinked)
			this.unshrink();
		else {
			this.shrink();
		}
	},

	maximize: function () {
		this.unshrink();
		this._mx_svx = this.element.offsetLeft;
		this._mx_svy = this.element.offsetTop;
		this._mx_svw = this.element.offsetWidth;
		this._mx_svh = this.element.offsetHeight;

		this.setSize (windowWidth() - 20, windowHeight() - 20);
		this.setPosition (10, 10);
		//this.arrange(5, 10, w_w, w_h);

		if (this.playlist.visible) this.showHidePlaylist();
		if (this.infoVisible) this.showHideInfo();

		this.maximized = true;
		Element.addClassName (this.element, 'maximized');
		this.btnMaximizeRestore.title = 'Restore';
	},
	restore: function () {
		this.unshrink();
		if (this.minimized) {
			this.element.style.visibility = 'visible';
			this.minimized = false;
			Element.removeClassName (this.element, 'minimized');
		} else if (this.maximized) {
			this.setSize(this._mx_svw, this._mx_svh);
			this.setPosition (this._mx_svx, this._mx_svy);
			this.maximized = false;
			Element.removeClassName (this.element, 'maximized');
		}
		this.b_c.setForeground(this);
		this.btnMaximizeRestore.title = 'Maximize';
	},
	shrink: function () {
		if (this.shrinked) return;
		this.shrinked = true;
		this.l_col.style.visibility = this.playlist_element.style.visibility = this.resizer.style.visibility = 'hidden';
		this.element.style.height = "38px";
		Element.addClassName (this.element, 'shrinked');
		this.btnShrink.title = 'Restore';
		if (this.b_c.pauseOnMinimize) this.pauseIfPlaying();
	},
	unshrink: function () {
		if (!this.shrinked) return;
		this.element.style.height = this.height + "px";
		this.l_col.style.visibility = this.playlist_element.style.visibility = this.resizer.style.visibility = '';
		this.shrinked = false;
		Element.removeClassName (this.element, 'shrinked');
		this.btnShrink.title = 'Shrink';
	},

	loadVideo: function (jsonObj) {
		this.jsonObj = jsonObj;
		//this.jsonObj.real_length = parseInt(this.jsonObj.real_length);
		var openEmpty = false;
		if (arguments.length == 0) {
			openEmpty = true;
			this.jsonObj = null;
		}
		if (this.FO) {
			Movie (this.flashObjectElement.id).loadFile('http://www.youtube.com/watch?v=' + jsonObj.id);
		} else {
			var w = this.calcFOWidth(); // '425px';
			var h = this.calcFOHeight();//'360px'; //'300px';
			//alert (hasFlashVersion);
			if (!hasFlashVersion) {
				this.flashObjectElement.innerHTML = '<div class="noflash" style="width:' + w + 'px;height:' + h + 'px"><div>You need <a href="http://www.macromedia.com/go/getflashplayer" title="Download Adobe Flash Player" target="_blank">Adobe Flash Player</a> to view the video</div></div> '
				this.noFlashVersionElement = this.flashObjectElement.getElementsByTagName('div')[0]; // stupiiiid
				this.FO = {width:w, height:h};
				downloadFlashPlayer();
			} else {
				this.FO = new SWFObject("flvplayer2.swf", this.flashObjectElement.id+"_flashobject", w + "px", h + "px", "8");
				this.FO.addParam("allowfullscreen","true");
				this.FO.addParam("wmode","opaque");
				this.FO.addVariable("width", w);
				this.FO.addVariable("height", h);
				this.FO.addVariable("logo", "/images/watermark.png");
				this.FO.addVariable("autostart", this.noAutostart?"false":"true");
				this.FO.addVariable("start", "true");
				if (!openEmpty) {
					this.FO.addVariable("file", "http://www.youtube.com/watch?v=" + jsonObj.id);
					this.FO.addVariable("image", jsonObj.thumbnail_url);
					
					var ch = jsonObj.length_seconds.split(':');
					var s = myParseInt (ch[ch.length - 1]) + myParseInt (ch[ch.length - 2]) * 60 + (ch.length > 2 ? myParseInt(ch[ch.length - 3])  * 60 * 60 : 0);
					this.FO.addVariable("fake_duration", s);
				} else {
					this.FO.addVariable("image", SHOST + "/images/none.gif");
				}
				this.FO.addVariable("overstretch", "false");
				//this.FO.addVariable("theme", "/White.player.xml");
				this.FO.addVariable("theme", ThemesChooser.currentTheme.jsonObj.playerXML);
				this.FO.addVariable("enablejs", "true");
				this.FO.addVariable("ID", this.flashObjectElement.id);
				this.FO.addVariable("prev_next_status", this.playlist.get_prev_next_status());
				this.FO.addParam("allowscriptaccess","always");
				this.FO.addVariable("id", this.flashObjectElement.id+"_flashobject");

				this.FO.write(this.flashObjectElement.id);
				this.FO.width = w;
				this.FO.height = h;
			}
		}

		this.playlist.updateFlashObject();
		if (!openEmpty) {
			this.titleElement.innerHTML = jsonObj.title + " - (" + this.jsonObj.author + ")";

			var round_rating = Math.round(2 * this.jsonObj.rating_avg);
			for (var i = 0; i < 5; i ++) {
				this.ratingStar[i].title = 'Rating: ' + this.jsonObj.rating_avg;
				Element.removeClassName (this.ratingStar[i], 'half');
				Element.removeClassName (this.ratingStar[i], 'full');
				Element.removeClassName (this.ratingStar[i], 'none');
				var s = round_rating - (2*i);
				if (s < 1) 	Element.addClassName (this.ratingStar[i], 'none'); else
				if (s == 1)	Element.addClassName (this.ratingStar[i], 'half');
				else		Element.addClassName (this.ratingStar[i], 'full');
			}

			this.linkAllComments.href = "http://www.youtube.com/comment_servlet?all_comments&v=" + this.jsonObj.id;

			this.infoBoxTabDescription.body_in.innerHTML = '<br /><strong>' + parseDescription(this.jsonObj.description) + '</strong>';
			this.infoBoxTabDescription.scroll.update();
			this.infoBoxTabProfile.body_in.innerHTML = 'Loading user profile...';
			this.infoBoxTabProfile.scroll.update();

			this.btnYouTube.href = 'http://www.youtube.com/watch?v=' + jsonObj.id;
			this.URLinput.value = 'http://' + CHOST + '/?watch=' + jsonObj.id;

			this.btnFavorites.setHeadTitleAttr('Favorite videos of ' + this.jsonObj.author); //+ "'s favs";
			this.btnMoreVideos.setHeadTitleAttr('More videos from ' + this.jsonObj.author);//+ "'s favs";
			this.btnRelatedVideos.setHeadTitleAttr('Videos related to "' + this.jsonObj.title + '"');

			this.trayElement.setObjectPlayer (this.jsonObj, this);

			new Ajax.Request ("video_played.php", {
				method:"post", parameters: "jsonObj=" + escape(VideoToJSONString(jsonObj)) + "&id=" + jsonObj.id
			});

			this._loadingNewVideo = true;
			this._loadedCommentsCount = 0;
			this.infoBoxTabComments.body_in.innerHTML = 'Loading comments...';
			new Ajax.Request ("/get_details.php", {
				method:"get", parameters: "id=" + jsonObj.id, onSuccess: this.getComments_handle.bind(this)
			});

			this.infoBoxTabComments.scroll.update();
			new Ajax.Request ("/get_profile.php", {
				method:"get", parameters: "user=" + jsonObj.author, onSuccess: this.getProfile_handle.bind(this)
			});

			urchinTracker('video_played/' + this.jsonObj.id);
		} else {
			this.titleElement.innerHTML = '';
			for (var i = 0; i < 5; i ++) {
				Element.addClassName (this.ratingStar[i], 'none');
				this.ratingStar[i].title = '';
			}
			this.linkAllComments.href = 'http://' + CHOST + '/';
			this.infoBoxTabDescription.body_in.innerHTML = '';
			this.infoBoxTabDescription.scroll.update();
			this.infoBoxTabProfile.body_in.innerHTML = '';
			this.infoBoxTabProfile.scroll.update();
			this.infoBoxTabComments.body_in.innerHTML = '';
			this.infoBoxTabComments.scroll.update();

			this.btnYouTube.href = 'http://www.youtube.com/';
			this.URLinput.value = '';
			this.btnFavorites.title = '';
			this.btnMoreVideos.title = '';

			this.playlist.showEmptyPlaylistMessage();

			this.trayElement.setObjectPlayer (null, this);
		}
	},

	onCommentsScrollUpdated: function (value) {
		/*this._loadingNewVideo = false;
		if (value == 100 && this._loadedCommentsCount < this.jsonObj.comment_count) {
			new Ajax.Request ("get_details.php", {
				method:"get", parameters: "conly=yes&page=" + Math.round((this._loadedCommentsCount / 25) + 1) +"&id=" + this.jsonObj.id, onSuccess: this.getComments_handle.bind(this)
			});
		}*/
	},

	getComments_handle: function (ajaxResponse) {
		var t = ajaxResponse.responseText;
		var jsonObj = null;
		var currsec = new Date().getTime() / 1000;
		eval ('jsonObj = ' + t);
		if (jsonObj != null) {
			this.jsonObj.comments = jsonObj.comments;
			if (this._loadingNewVideo)
				this.infoBoxTabComments.body_in.innerHTML = '';
			else
				if (jsonObj.comments.length > 0)
					this.infoBoxTabComments.body_in.innerHTML += '<div class="comments_separator"></div>';
			for (var i = 0; i < jsonObj.comments.length; i ++) {
				var secs_ago = (currsec - parseInt(jsonObj.comments[i].time)) ;
				var timeText = '';
				if (secs_ago < 60)
					timeText = '1 minute';
				else
				if (secs_ago < 60*59)
					timeText = Math.ceil(secs_ago / 60) + " minutes";
				else
				if (secs_ago < 60*60*23)
					timeText = Math.ceil(secs_ago / (60*60)) + " hours";
				else
				if (secs_ago < 60*60*24*31)
					timeText = Math.ceil(secs_ago / (60*60*24)) + " days";
				else
					timeText = Math.ceil(secs_ago / (60*60*24*31)) + " months";
				this.infoBoxTabComments.body_in.innerHTML += '<span class="comment_user">' + jsonObj.comments[i].author + "</span> " +
					"<span class=\"comment_date\">(" + timeText + " ago)</span><br /><div class=\"video_comment\">" + parseDescription(jsonObj.comments[i].text) + "</div>";
				if (i < jsonObj.comments.length - 1)
					this.infoBoxTabComments.body_in.innerHTML += '<div class="comments_separator"></div>';
			}
			this._loadedCommentsCount += jsonObj.comments.length;
			if (jsonObj.comments.length < this.jsonObj.comment_count)
				//this.spanCommentsCount.innerHTML = ' (' + this._loadedCommentsCount + ' of ' + this.jsonObj.comment_count + ')';
				this.spanCommentsCount.innerHTML = ' (last ' + this._loadedCommentsCount + ')';
			else
				this.spanCommentsCount.innerHTML = ' (' + this._loadedCommentsCount + ')';
			this.infoBoxTabComments.scroll.update();
		}
	},

	getProfile_handle: function (ajaxResponse) {
		var t = ajaxResponse.responseText;
		var jsonObj = null;
		eval ('jsonObj = ' + t);
		if (jsonObj != null) {
			var cnt = '';
			if (jsonObj.thumbnail)
				cnt += '<img src="' + jsonObj.thumbnail + '" class="profile_thumb" alt="" />';
			cnt += '<br />'
			cnt += "<span class=\"profile_tag\">Name:</span> " + jsonObj.first_name + " " + jsonObj.last_name + "<br />";
			if (jsonObj.homepage)
				cnt += "<span classs=\"profile_tag\">Homepage:</span> <a href=\"" + jsonObj.homepage + "\" target=\"_blank\">" + jsonObj.homepage + "</a><br />";
			if (jsonObj.age)
				cnt += "<span class=\"profile_tag\">Age:</span> " + jsonObj.age + "<br />";
			if (jsonObj.gender)
				cnt += "<span class=\"profile_tag\">Gender:</span> "  + (jsonObj.gender == 'm'?'Male':'Female') + "<br />";
			if (jsonObj.country)
				cnt += "<span class=\"profile_tag\">Country:</span> " + jsonObj.country + "<br />";
			if (jsonObj.hometown)
				cnt += "<span class=\"profile_tag\">Home town:</span> " + jsonObj.hometown + "<br />";
			if (jsonObj.occupation)
				cnt += "<span class=\"profile_tag\">Occupation:</span> " + jsonObj.occupation + "<br />";

			if (jsonObj.subscribers_count)
				cnt += "<span class=\"profile_tag\">Subscribers:</span> " + jsonObj.subscribers_count + "<br />";
			if (jsonObj.uploads_count)
				cnt += "<span class=\"profile_tag\">Uploads:</span> " + jsonObj.uploads_count + "<br />";

			this.infoBoxTabProfile.body_in.innerHTML = cnt;
		}
	},

	showUserFavorites: function () {
		if (this.jsonObj)
			show_favorites_of_user(this.jsonObj.author);
	},
	showUserVideos: function () {
		if (this.jsonObj)
			show_videos_by_user(this.jsonObj.author);
	},
	showRelatedVideos: function () {
		if (this.jsonObj)
			show_videos_related(this.jsonObj.id, this.jsonObj.title);
	},

	onClickTray: function (event) {
		if (this.minimized)
			this.restore(event)
		else if (this.shrinked)
			this.unshrink();
		else
			this.b_c.setForeground(this);
	},

	getUpdate: function (type, param1, param2) {
		if (this.doDoNotStartOnLoad && type == "time" && param1 > 0) {
			// the problem is that we cannot send the update before we are sure the flash is loaded.
			// that's why we do it here!
			this.doDoNotStartOnLoad = !this.pauseIfPlaying();
		}
		eval ("this.pu_" + type + " = " + param1 );
		if (type=="time" && param1 > this.jsonObj.real_length - 2 && this.pu_state == 2) { // the current playing item is over
			this.playlist.currentPlayingIsOver();
			return;
		} else if (type=="state" && !this.minimized) {
			return;
		} else if (type=="shareVideo") {
			this.recommend();
			return;
		} else if (type=="copyToClipBoard") {
			if (!this._urlInputVisible)
				this.switchFooterURL();
			return;
		} else if (type=="downloadFlv" || type=="downloadFLV") {
			this.downloadFLV();
			return;
		} else if (type=="downloadMovie") {
			this.downloadConverted();
			return;
		} else if (type=="next") {
			this.playlist.clickPlayNext();
			return;
		} else if (type=="prev") {
			this.playlist.clickPlayPrev();
			return;
		}
	},

	restartCurrentVideo: function () {
		Movie(this.flashObjectElement.id).sendEvent('scrub', 0, 0);
		Movie(this.flashObjectElement.id).sendEvent('stop', 0, 0);
		Movie(this.flashObjectElement.id).sendEvent('playpause', 0, 0);
	},

	downloadConverted: function (event) {
		if (this.jsonObj)
			Converter.downloadConverted (this.jsonObj);
	},

	downloadFLV: function (event) {
		if (this.jsonObj)
			Converter.downloadFLV (this.jsonObj);
	},

	recommend: function (event) {
		if (this.jsonObj)
			send_recommendation(this.jsonObj.id, this.jsonObj.title);
	},

	closeBox: function (event) {
		if (this.playlist.playlistModified) {
			if (this.playlist.loadedPlaylistId) {
				if (confirm ('The playlist has been modified. Do you want to save it?')) {
					this.playlist.savePlaylist();
				}
			}
		}
		if (isIE) {
			var obj = this.flashObjectElement.getElementsByTagName('object')[0];
			if (obj) {
				obj.style.display = 'none';
				for (var x in obj) {
					if (typeof obj[x] == 'function') {
						obj[x] = function(){};
					}
				}
			}
		}
		this.trayElement.remove();
		this.eltop = this.element.offsetTop;
		this.elleft = this.element.offsetLeft;
		this.element.style.display = 'none';
		this.element.innerHTML = '';
		if (isIE) IEForceRedraw();
		this.b_c.removeWindow(this);
	},

	startMoving: function(event) {
		if (this.moving) {
			this.endMoving(event);
			return;
		}
		this.moving = true;

		this.maximized = false;
		this.b_c.setForeground(this);

		this.oX = Event.pointerX(event) - this.element.offsetLeft;
		this.oY = Event.pointerY(event) - this.element.offsetTop;
		this._mX = windowWidth() - this.width;
		this._mY = windowHeight() - (this.shrinked?38:this.height);

		Event.observe(document, "mouseup", this._endMoving);
  		Event.observe(document, "mousemove", this._updateMoving);

  		Event.stop(event);
 	},

	updateMoving: function(event) {
		if (!this.moving) return;
		Event.stop(event);
		var nx = Event.pointerX(event) - this.oX;
		var ny = Event.pointerY(event) - this.oY;

		this.element.style.left = (nx<0?0:(nx>this._mX?this._mX:nx)) + 'px';
		this.element.style.top = (ny<0?0:(ny>this._mY?this._mY:ny)) + 'px';
		/*if (isIE6) {
			this.nx = nx - (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
			this.ny = ny - (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
		}*/
	},

	endMoving: function(event) {
		if (!this.moving) return;
		this.moving = false;
		Event.stop(event);

		Event.stopObserving(document, "mouseup", this._endMoving);
  		Event.stopObserving(document, "mousemove", this._updateMoving);

  		this.restore_top = this.element.style.top;
  		this.restore_left = this.element.style.left;
  		this.eltop = parseInt(this.element.style.top);
		this.elleft = parseInt(this.element.style.left);
	},

	ResizeStart: function (event) {
		if (this.resizing) {
			this.ResizeEnd(event);
			return;
		}
		this.resizing = true;
		this.maximized = false;
		Element.removeClassName (this.element, 'maximized');
		this.btnMaximizeRestore.title = 'Maximize';

		this.oX = Event.pointerX(event) - this.element.offsetWidth;
		this.oY = Event.pointerY(event) - this.element.offsetHeight;
		Event.observe(document, "mouseup", this._resizeEnd);
  		Event.observe(document, "mousemove", this._resizeUpdate);
  		Event.stop(event);
	},

	ResizeUpdate: function (event) {
		if (!this.resizing) return;
		Event.stop(event);

		this.width = Math.max (Event.pointerX(event) - this.oX, PLAYER_MIN_WIDTH);
		this.height = Math.max (Event.pointerY(event) - this.oY, PLAYER_MIN_HEIGHT);

		this.element.style.width = this.width + "px";
		this.element.style.height = this.height + "px";

		this.updateSizes();
	},

	ResizeEnd: function(event) {
		if (!this.resizing) return;
		this.resizing = false;
		Event.stop(event);

		Event.stopObserving(document, "mouseup", this._resizeEnd);
  		Event.stopObserving(document, "mousemove", this._resizeUpdate);
	},

	resizeInfoPanelStart: function (event) {
		if (this.inforesizing) {
			this.resizeInfoPanelEnd(event);
			return;
		}
		this.inforesizing = true;
		this.oY = this.element.offsetTop + this.element.offsetHeight;
		Event.observe(document, "mouseup", this._resizePanelEnd);
  		Event.observe(document, "mousemove", this._resizePanelUpdate);
  		Event.stop(event);
	},
	resizeInfoPanelUpdate: function (event) {
		if (!this.inforesizing) return;
		Event.stop(event);
		var nh = this.oY - Event.pointerY(event) - 27;
		if (this.height - nh - PLAYER_MIDBUTTONS_HEIGHT - PLAYER_HEADER_HEIGHT < 100)
			return;
		if (nh != this.infoPanelHeight && nh > 50) {
			this.infoPanelHeight = this.oY - Event.pointerY(event) - INFO_PANEL_RESIZER_OFFSET_HEIGHT;

			this.updateSizes();
		}
	},
	resizeInfoPanelEnd: function (event) {
		if (!this.inforesizing) return;
		this.inforesizing = false;
		Event.stop(event);
		Event.stopObserving(document, "mouseup", this._resizePanelEnd);
  		Event.stopObserving(document, "mousemove", this._resizePanelUpdate);
	},

	arrange: function (x, y, width, height) {
		/* this function is left for backwords compatibility with rest of the site */
		this.setSize(width, height);
		this.setPosition(x, y);
	},
	setSize: function (w, h) {
		this.width = w;
		this.height = h;
		this.element.style.width = this.width + "px";
		this.element.style.height = this.height + "px";
		this.updateSizes();
	},
	setPosition: function (x, y) {
		this.element.style.top = y + "px";
		this.element.style.left = x + "px";
	},

	calcFOWidth: function () {
		return this.width - (this.playlist.visible?PLAYLIST_ELEMENT_OPEN_WIDTH:PLAYLIST_ELEMENT_CLOSED_WIDTH);
	},
	calcFOHeight: function () {
		return this.height - (this.infoVisible?this.infoPanelHeight:0) - (this._urlInputVisible?PLAYER_URL_HEIGHT:0) - PLAYER_MIDBUTTONS_HEIGHT - PLAYER_HEADER_HEIGHT;
	},

	// purpose is - when cahnging the look of the player this fixes all problems
	updateSizes: function () {
		if (this.playlist && this.FO) {
			this.FO.width = this.calcFOWidth();
			this.FO.height = this.calcFOHeight();
			if (!hasFlashVersion) {
				this.noFlashVersionElement.style.width = this.FO.width + "px";
				this.noFlashVersionElement.style.height = this.FO.height + "px";
			} else {
				$(this.flashObjectElement.id + '_flashobject').style.width = this.FO.width + "px";
				$(this.flashObjectElement.id + '_flashobject').style.height = this.FO.height + "px";
			}
			this.URLinput.style.width = this.calcFOWidth() - (isIE?0:6) + "px";
			this.playlist.resize();
			if (isIE6) this.btnShowHidePlaylist.style.top = (this.calcFOHeight() / 2) - 5 + "px";
			if (isIE6) this.infoBox.fixWidth (this.calcFOWidth());
		}
		if (isIE6) this.bmid.style.width = this.width - 12 + "px";
		if (this.playlist) this.playlist.resize();
		if (this.infoBox) this.infoBox.setHeight (this.infoPanelHeight);

	},

	openVideo: function (jsonObj) {
		this.playlist.clearPlaylist();
		this.playlist.addToPlaylist(jsonObj);
		this.playlist.playSelected();
	},
	appendVideo: function (jsonObj) {
		this.playlist.addToPlaylist(jsonObj);
	},

	// these are for the embeding
	savePlayerState: function () {
		this.savedState = {
			left: this.element.offsetLeft,
			top: this.element.offsetTop,
			width: this.width,
			height: this.height,
			playlistVisible: this.playlist.visible,
			infoVisible: this.infoVisible
		}
	},
	setInfoEnabled: function (enable) {
		this.btnShowHideInfo.style.display = enable?'':'none';
	},
	setPlaylistEnabled: function (enable) {
		this.btnShowHidePlaylist.style.display = enable?'':'none';
	},
	restorePlayerState: function () {
		this.setInfoEnabled(true);
		this.setPlaylistEnabled(true);
		if (this.savedState.playlistVisible != this.playlist.visible) this.showHidePlaylist();
		if (this.savedState.infoVisible != this.infoVisible) this.showHideInfo();
		this.setSize(this.savedState.width, this.savedState.height);
		this.setPosition(this.savedState.left, this.savedState.top);
	},

	centerPlayer: function () {
		this.element.style.top = (windowHeight() - this.height) / 2 + "px";
		this.element.style.left = (windowWidth() - this.width) / 2 + "px";
	},

	onThemeChange: function () {
		//ie_debug(ThemesChooser.currentTheme.jsonObj.playerXML);
		Movie(this.flashObjectElement.id).setSkin(ThemesChooser.currentTheme.jsonObj.playerXML);
		//ie_debug('skin set');
		this.infoBox.onThemeChange();
	}
};

/* ----------------------- */

var PlayersContainer = Class.create();
PlayersContainer.prototype = {
	initialize: function (container) {
		this.element = $(container);
		this.players = new Array ();

		if (isIE6) window.onscroll = this.windowScrolled.bindAsEventListener(this);
		this.nextID = 1;

		this.pauseOnMinimize = true;
		if (typeof onl_pom_state != "undefined") {
			if (onl_pom_state == false)
				//this.switchPauseOnMinimize();
				this.pauseOnMinimize = false;
		} else
			if (Cookies.getValue('pom_state', 'true') == 'false')
				//this.switchPauseOnMinimize();
				this.pauseOnMinimize = false;

		Settings.setPauseOnMinimize (this.pauseOnMinimize?'on':'off');
		this.switchPauseOnMinimize(this.pauseOnMinimize?'on':'off');

		this.dimming = false;
		if (typeof onl_dim_state != "undefined") {
			if (onl_dim_state == true)
				//this.switchDimming();
				this.dimming = true;
		} else
			if (Cookies.getValue('dim_state', 'false')=='true')
				//this.switchDimming();
				this.dimming = true;
		Settings.setDimOnPlay (this.dimming?'on':'off');
		this.switchDimming (this.dimming?'on':'off');
		Event.observe(window, 'resize', this.onWindowResize.bind(this));
	},
	onWindowResize: function () {
		for (var i = 0; i < this.players.length; i ++)
			this.players[i].onWindowResize();
	},

	getNextID: function () {
		return this.nextID++;
	},

	openVideo: function (jsonObj, player) {
		if (arguments.length == 1 || player < 0 || typeof(player) == "undefined") {
			this.openNewVideo(jsonObj);
		} else {
			this.players[player].appendVideo (jsonObj);
			if (this.players[player].minimized)
				this.players[player].restore();
		}
	},

	openNewVideo: function (jsonObj) {
		var a = new Player(this);
		a.openVideo(jsonObj);
		this.players.push(a);
		a.plind = this.players.length - 1;
		this.setForeground(a);
	},

	openSavedPlaylist: function(jsonObj, playVideo) { // playVide may be id, index or 'none'!
		var a = new Player(this);
		a.playlist.addToPlaylistMultiple(jsonObj.videos,'load_playlist'); // set the parameter so that the function knows how to insert them
		this.players.push(a);
		this.setForeground(a);
		a.plind = this.players.length - 1;
		a.playlist.selectItem(0);
		if (arguments.length == 2) {
			if (typeof(playVideo) == "string") {
				if (playVideo == 'none') {
					a.noAutostart = true;
					a.playlist.selectItem(0);
				} else {
					for (var i = 0; i < jsonObj.videos.length; i ++)
						if (jsonObj.videos[i].id == playVideo) {
							// ok, this video is to be played when player starts
							a.playlist.selectItem(i);
							break;
						}
				}
			} else
				a.playlist.selectItem(playVideo);
		}
		a.playlist.playSelected();
		a.playlist.loadedPlaylistName = jsonObj.name;
		a.playlist.loadedPlaylistId = jsonObj.id;
		a.playlist.loadedPlaylistDescription = jsonObj.description;
		a.playlist.playlistModified = false;
		a.playlist.updatePlaylistMenuButton();
		a.playlist.showPlaylist();
		//setTimeout (a.playlist.updateScrollbar.bind(a.playlist), 1000);
	},

	openEmptyPlayer: function () {
		var a = new Player(this);
		this.players.push(a);
		this.setForeground(a);
		a.plind = this.players.length - 1;
		a.playlist.showPlaylist();
		a.loadVideo();
	},

	// for the embedding
	openExampleEmbedPlayer: function (jsonArr) {
		var a = new Player(this);
		a.playlist.addToPlaylistMultiple(jsonArr,'load_playlist'); // set the parameter so that the function knows how to insert them
		this.players.push(a);
		this.setForeground(a);
		a.plind = this.players.length - 1;
		a.playlist.selectItem(0);
		a.doDoNotStartOnLoad = true;
		a.playlist.playSelected();
		return a;
	},

	// this is called by the window when it's closed
	removeWindow: function (player) {
		this.releaseForeground(player);
		this.players = this.players.without(player);
		// fix the currentForegroundPlayer
		var max = 0, max_i = -1;
		for (var i = 0; i < this.players.length; i ++)
			if ((this.players[i]) && (this.players[i].element.style.zIndex > max))
				max_i = i;
		if (max_i > -1) this.currentForegroundPlayer = max_i;
		if (player.maximized) {
			player.elleft = player._mx_svx;
			player.eltop = player._mx_svy;
			player.width = player._mx_svw;
			player.height = player._mx_svh;
		}
		Cookies.setValue ('ps', player.width + ',' + player.height + ',' + player.elleft + ',' + player.eltop + ',' +
			player.infoPanelHeight + ',' + (player.infoVisible?'true':'false') + ',' + (player.playlist.visible?'true':'false') , 1000);
		delete player;
	},

	setForeground: function (player) { // each player calles this when wants to go on front... big problem with flash players
		var zi = parseInt(player.element.style.zIndex) || 900;
		var z = 0;
		player.element.style.zIndex = 900;
		for (var i = 0; i < this.players.length; i++)
			if (this.players[i] && this.players[i].element && parseInt(this.players[i].element.style.zIndex) >= zi) {
				z = parseInt(this.players[i].element.style.zIndex);
				setTimeout ("updateZ(" + i + ", " + (z-5) + ");", 100);
				//this.players[i].main.style.zIndex = z - 5; - some strange bug happens with this... with setTimeout it shits rarely
			}
		for (var i = 0; i < this.players.length; i++)
			if (player == this.players[i]) {
				this.currentForegroundPlayer = i;
				return;
			}
	},

	releaseForeground: function (player) { }, // the foreground window releases focus to the next one

	windowScrolled: function () {
		for (var i = 0; i < this.players.length; i++) {
			this.players[i].main.style.left = (this.players[i].nx + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft)) + 'px';
			if (this.players[i].main.style.top != '')
				this.players[i].main.style.top = (this.players[i].ny + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop)) + 'px';
		}
	},

	sendUpdate: function(playerID, type, param1, param2) {
		for (var i = 0; i < this.players.length; i ++)
			if (this.players[i].flashObjectElement.id == playerID) {
					this.players[i].getUpdate(type, param1, param2);
					return;
			}
	},

	closeAll: function (event) {
		for (var i = this.players.length-1; i >= 0; i--)
			this.players[i].closeBox();
	},

	arrange: function (event) {
		if (this.players.length == 0) return;
		var w_w = window.innerWidth - 20; //20 is for the scroller
		var w_h = window.innerHeight - 37;
		var rows = 0;
		var cols = 0;
		var player_w = -1;
		var player_h = -1;
		var n = this.players.length;
		var crows = 0;
		var ccols = 0;
		var x, y, r, c, maxw, maxh, new_player_w;

		while (n >= 1) {
			//estimate size of windows for n columns
			ccols = n;
			crows = Math.ceil (this.players.length / n);

			//we leave at least 10px space between players
			maxw = Math.floor((w_w - (ccols*10 + 10)) / ccols);
			maxh = Math.floor((w_h - (crows*10 + 10)) / crows);
			//remember to keep aspect of window to 5/3 or 5/4  - with or without playlist
			if (maxw/5 > maxh/3)
				new_player_w = Math.floor ( 5 * maxh / 3);
			else
				new_player_w = maxw;
			//compare to what found so far as best. Compare only width
			if (new_player_w > player_w ) {
				player_w = new_player_w;
				rows = crows;
				cols = ccols;
			}
			if (n > 1) n = Math.ceil (n/2); else n = 0;
		}
		//OK... so far we found how to split them
		player_h = Math.floor(player_w * 3 / 5);
		var offsetLeft = Math.floor((w_w - (cols * player_w + (cols + 1) * 10)) / 2);
		var offsetTop = 37 + Math.floor((w_h - (rows * player_h + (rows + 1) * 10)) / 2);
		//alert (rows + "\n" + cols + "\n" + player_w + "\n" + player_h);
		for (var i = 0; i < this.players.length; i ++ ) {
			r = Math.floor ( i / cols);
			c = i % cols;
			x = offsetLeft + c * player_w + (c + 1) * 10;
			y = offsetTop + r * player_h + (r + 1) * 10;
			this.players[i].arrange(x, y, player_w, player_h);
		}
	},

	checkNoPlayers : function () {
		if (this.players.length == 0)
			this.no_players.style.display = 'block';
		else
			this.no_players.style.display = 'none';
	},

	// following two functions are used by modal boxes!
	pauseAllPlayers: function () { // pauses all running players
		for (var i = 0; i < this.players.length; i ++)
			if (this.players[i].pauseIfPlaying())
				this.players[i].pausedByContainer = true;
	},

	unpauseAllPlayers: function () { // if the prev function paused player, resume it
		for (var i = 0; i < this.players.length; i ++)
			if (this.players[i].pausedByContainer)
				this.players[i].playIfPaused();
	},
	// these are used by the background. Due to the windowed/windowless objects' z-index we have to
	// hide the flash objects when showing background
	hideAllFlashObjects: function () {
		for (var i = 0; i < this.players.length; i ++)
			this.players[i].flashObjectElement.style.visibility = "hidden";
	},
	unhideAllFlashObjects: function () {
		for (var i = 0; i < this.players.length; i ++)
			this.players[i].flashObjectElement.style.visibility = "";
	},
	// user stuff...
	userHasLoggedIn: function () {
		for (var i = 0; i < this.players.length; i ++)
			this.players[i].playlist.userHasLoggedIn();
	},
	userHasLoggedOut: function () {
		for (var i = 0; i < this.players.length; i ++)
			this.players[i].playlist.userHasLoggedOut();
	},

	onThemeChange: function () {
		for (var i = 0; i < this.players.length; i ++)
			this.players[i].onThemeChange();
	},

	switchPauseOnMinimize: function (state) {
		if (arguments.length == 1)
			this.pauseOnMinimize = (state == 'on' || state === true);
		else
			this.pauseOnMinimize = !this.pauseOnMinimize;
	},

	switchDimming: function (state) {
		if (arguments.length == 1)
			this.dimming = (state == 'on' || state === true);
		else
			this.dimming = !this.dimming;

		if (this.dimming) {
			this.eventMouseMove = this.onMouseMove.bindAsEventListener(this);
			Event.observe(document, "mousemove", this.eventMouseMove);
			this.onMouseMove();
		} else {
			if (this.eventMouseMove)
				Event.stopObserving(document, "mousemove", this.eventMouseMove);
			if (this.dimTimer) {
				clearTimeout(this.dimTimer);
				this.dimTimer = -1;
			}
		}
	},
	onMouseMove: function () {
		if (this.dimming) {
			if (this.dimTimer)
				clearTimeout(this.dimTimer);
			if (this.dimmed) this.removeDim();
			this.dimTimer = setTimeout (this.startDim.bind(this), 7000);
		}
	},
	startDim: function () {
		if (this.players.length == 0) return;
		var active = 0;
		for (var i = 0; i < this.players.length; i ++)
			if (!this.players[i].minimized && this.players[i].pu_state != 0)
				active++;
		if (!active) return;
		if (!this.dimming) return;
		this.dimmed = true;
		$('dim_background').style.display = 'block';
		setTimeout("$('dim_background').style.zIndex = $('dim_background').style.zIndex?'':'701'", 100);
	},
	removeDim: function () {
		this.dimmed = false;
		$('dim_background').style.display = 'none';
	},

	closePlayerMenus: function () {
		for (var i = 0; i < this.players.length; i++)
			this.players[i].playlist.hidePlaylistMenu();
	}
}

/* blah.. */
function updateZ (i, z) {
	//alert ("updateZ " + i + " " +  z);
	if (i < bc.players.length)
		bc.players[i].element.style.zIndex = z;
}

/* hook to updates from players */
function getUpdate (playerID, type, param1, param2) {
	bc.sendUpdate(playerID, type, param1, param2);
}

//parses the description and returns it whith the URLs converted to links
var RE = /((?:http(?:s?):\/\/)(?:www\.)?(?:[a-zA-Z0-9\/\.\-\_\?\&\=]+))/g;
function parseDescription(descr) {
	return descr.replace(RE, "<a href='$1' target='_blank'>$1</a>").replace (/&lt;/g, '<').replace(/&gt;/g, '>');
}

function getDataFromPlayer (playerIndex) {
	return bc.players[playerIndex].playlist.getVideosJsonArr();
}