
/**
 * 	jQuery player
 *	@author alvin@extro.com.au
 */
(function($) {
	$.fn.player = function(options) {
		
		// default options
		var defaults = {
			'swf': '/swf/flowplayer/flowplayer-3.2.1.swf'
		};

		if (options) {
			options = $.extend(defaults, options);
		}
		else {
			options = defaults;
		}

		//	helper functions
		var truncate = function(text) {
			text = String(text);
			if (text.length > 15) {
				text = text.substr(0, 13) + '...';
			}
			return text;
		};
		var log = function(arg) {
			if (window['console'] && console['log']) {
				console.log(arg);
			}
		};

		// iterate over matched elements
		return this.each(function() {

			
			var TrackHelper = {
				'favouriteUrl': function(track) {
					if (!track['model']) {
						return false;
					}
					return '/user_favourites/add_favourite/' + track['model'] + '/' + track['id'];
				},
				'profileUrl': function(track) {
					if (!track['model'] || track['model'] != 'Mixtape') {
						return false;
					}
					return '/mixtapes/profile_redirect/' + track['id'];
				},
				'profileImageUrl': function(track) {
					if (!track['model'] || track['model'] != 'Mixtape') {
						return false;
					}
					return '/mixtapes/profile_image/' + track['id'];
				},
				'tracklistUrl': function(track) {
					if ((track == null) || !track['model'] || track['model'] != 'Mixtape') {
						return false;
					}
					return '/mixtapes/tracklist/' + track['id'];
				}
			};
			
			var Playlist = {
				'index': 0,
				'playlist': [],
				'setPlaylist': function(newPlaylist) {
					this.playlist = newPlaylist;
					this.index = 0;
				},
				'play': function(player) {
					if (this.playlist.length == 0) {
						return false;
					}
					if ((this.index == null) || (this.playlist[this.index] == null)) {
						return false;
					}
					player.play(this.playlist[this.index]['url']);
				},
				'resume': function(player) {
					var clip = player.getClip();
					if (clip == null) {
						
						player.play(this.playlist[this.index]['url']);
					}
					else {
						player.resume();
					}
				},
				'pause': function(player) {
					player.pause();
				},
				'nextTrack': function(player) {
					if (this.playlist.length > 0) {
						var nextIndex = (this.index + 1) % this.playlist.length;
						if (nextIndex != this.index) {
							this.index = nextIndex;
							player.stopBuffering();
							player.play(this.playlist[this.index]['url']);
						}
					}
				},
				'prevTrack': function(player) {
					if (this.playlist.length > 0) {
						var prevIndex = (this.index + this.playlist.length - 1) % this.playlist.length;
						if (prevIndex != this.index) {
							this.index = prevIndex;
							player.stopBuffering();
							player.play(this.playlist[this.index]['url']);
						}
					}
				},
				'currentTrack': function() {
					if (this.index !== null) {
						return this.playlist[this.index];
					}
					else {
						return null
					}
				},
				'togglePlayPause': function(player) {
					var clip = player.getClip();
					if (clip == null || !player.isPlaying()) {
						this.resume(player);
					}
					else {
						this.pause(player);
					}
				}
			};
			
			//	RadioPlaylist inherits from Playlist
			var RadioPlaylist = $.extend(
				{},
				Playlist,
				{
					'fadeOutTimeout': null,
					'nextTrackTimeout': null,
					'playlist': [],
					'play': function(player) {
						if (this.playlist.length == 0) {
							$controls.trigger('loading');
							//	Fetch playlist
							var self = this;
							$.ajax({
								url: '/radio/schedule.json',
								dataType: 'json',
								success: function(data) {
									if (playlist == RadioPlaylist) {
										self.playlist = data;
										self.play(player);
									}
								}
							})
							return true;
						}
						if ((this.index == null) || (this.playlist[this.index] == null)) {
							return false;
						}
						//	The time
						var now = (new Date()).getTime(); // Timestamp in milliseconds
						var startTime = new Date();
						var found = false;
						for (var i=0; i<this.playlist.length; i++) {
							var timeParts = this.playlist[i]['time'].split(':');
							startTime.setHours(parseInt(timeParts[0],10));
							startTime.setMinutes(parseInt(timeParts[1],10));
							startTime.setSeconds(parseInt(timeParts[2],10));
							if (startTime.getTime() - 5000 > now) { // Give about a 5 second window
								found = true;
								this.index = i - 1;
								break;
							}
						}
						if (!found) {
							//	We must not have an updated playlist, fetch another...
							return false;
						}
						player.stopBuffering();
						player.play(this.playlist[this.index]['url']);
						
						//	Set timeout to switch to next track
						now = (new Date()).getTime(); // Timestamp in milliseconds
						var remaining = startTime.getTime() - now;
						clearTimeout(this.nextTrackTimeout);
						this.nextTrackTimeout = setTimeout(
							function() {
								if ((playlist == RadioPlaylist) && (player.isPlaying())) {
									playlist.play(player);
								}
							},
							remaining
						);
					},
					'resume': function(player) {
						var clip = player.getClip();
						if (clip == null) {
							if (!this.playlist[this.index]) {
								this.play(player);
							}
							else {
								player.play(this.playlist[this.index]['url']);
							}
						}
						else {
							player.resume();
						}
					},
					'setPlaylist': function(newPlaylist) {
						// Switch to on-demand playlist
						$controls.trigger('radio-off');
						playlist = Playlist;
						playlist.setPlaylist(newPlaylist);
					},
					'nextTrack': function(player) {
						if (this.playlist.length > 0) {
							var nextIndex = (this.index + 1) % this.playlist.length;
							if (nextIndex != this.index) {
								this.index = nextIndex;
								this.setPlaylist(this.playlist);
								playlist.index = this.index;
								player.stopBuffering();
								playlist.play(player);
							}
						}
					},
					'prevTrack': function(player) {
						if (this.playlist.length > 0) {
							var prevIndex = (this.index + this.playlist.length - 1) % this.playlist.length;
							if (prevIndex != this.index) {
								this.index = prevIndex;
								this.setPlaylist(this.playlist);
								playlist.index = this.index;
								player.stopBuffering();
								playlist.play(player);
							}
						}
					}
				}
			);
			
			var playlist = RadioPlaylist;
			
			//	Setup flowplayer
			var $player = $(this).flowplayer(options.swf, { 
					clip: {
						autoPlay: true, 
						autoBuffering: false
					},
					plugins: { 
						controls: null,
						audio: {url: '/swf/flowplayer/flowplayer.audio-3.2.0.swf'}
					}, 
					onLoad: function() { 
						this.hide();
					},
					onBegin: function() {
						$controls.trigger('play');
					},
					onStart: function() {
						$controls.trigger('begin');
					},
					onResume: function() {
						$controls.trigger('play');
					},
					onPause: function() {
						$controls.trigger('pause');
					},
					onBufferEmpty: function() {
						$controls.trigger('buffering');
					},
					onBufferFull: function() {
						$controls.trigger('endbuffering');
					},
					onFinish: function() {
						$controls.trigger('pause');
						$controls.trigger('finish');
						playlist.nextTrack($player);
					},
					onError: function(errorCode, errorMessage) {
						alert('Player error: [' + errorCode + '] ' + errorMessage);
					}
				}
			);
			var player = $player.flowplayer(0);
			
			//	Bind control events
			var $controls = $(this).parents('.radio-bar').bind({
				'play': function() {
					$('.play-pause').removeClass('status-pause').addClass('status-play');
					$('.red-btn', $controls).removeClass('deactive').addClass('active');
					$controls.trigger('time-on');
				},
				'pause': function() {
					$('.play-pause').removeClass('status-play').addClass('status-pause');
					$('.red-btn', $controls).removeClass('active').addClass('deactive');
					$controls.trigger('time-off');
				},
				'loading': function() {
					$('.artist-details .title', $controls).text('');
					$('.artist-details .secondary-information', $controls).text('PULSE RADIO SCHEDULE IS LOADING...');
				},
				'buffering': function() {
					$('.artist-details .title', $controls).text('');
					$('.artist-details .secondary-information', $controls).text('PLEASE WAIT BUFFERING...');
				},
				'endbuffering': function() {
					$controls.trigger('updatetrack');
				},
				'updatetrack': function() {
					var track = playlist.currentTrack();
					if (track != null) {
						$('.artist-details .title', $controls).text(truncate(track['artist']));
						$('.artist-details .secondary-information', $controls).text(truncate(track['title']));
						
						var profileUrl = TrackHelper.profileUrl(track);
						var profileImageUrl = TrackHelper.profileImageUrl(track);
						var favouriteUrl = TrackHelper.favouriteUrl(track);

						$('.fav', $controls).attr('href', favouriteUrl);

						if (profileImageUrl) {
							$('.profile-image', $controls).addClass('profile-image-avail');
							$('.profile-image-img > img', $controls).attr('src', profileImageUrl);
							$('.profile-image-img', $controls).attr('href', profileUrl);
						}
						else {
							$('.profile-image', $controls).removeClass('profile-image-avail').slideUp('slow');
							$('.profile-image-img > img', $controls).attr('src', '/media/filter/233x233/transfer/img/profileimage/2010-04/noimage.jpg');
							$('.profile-image-img', $controls).attr('href', false);
						}
					}
					else {
						$('.artist-details .title', $controls).text('CLICK TO LISTEN TO THE RADIO');
						$('.artist-details .secondary-information', $controls).text('');
					}
				},
				'begin': function() {
					$controls.trigger('updatetrack');
					$controls.trigger('time-on');

					// Update schedule or tracklist if visible
					var $radioBarList = $('.radio-bar-list:visible', $controls);
					if (!!$radioBarList.length) {
						if ($radioBarList.hasClass('schedule-avail')) {
							$radioBarList.removeClass('schedule-avail');
							$('.schedule', $controls).trigger('click');
						}
						else if ($radioBarList.hasClass('tracklist-avail')) {
							$radioBarList.removeClass('tracklist-avail');
							$('.chart', $controls).trigger('click');
						}
					}
				},
				'finish': function() {
					$('.profile-image-avail', $controls).removeClass('profile-image-avail');
				},
				'radio-off': function() {
					$controls.addClass('radio-bar-on-demand');
				},
				'radio-on': function() {
					$controls.removeClass('radio-bar-on-demand');
				},
				'time-on': function() {
					if (timeInterval) {
						clearInterval(timeInterval);
					}
					timeInterval = setInterval(updateTime, 1500);
				},
				'time-off': function() {
					if (timeInterval) {
						clearInterval(timeInterval);
					}
				}
			});
			
			//	Update timer
			var timeInterval = null;
			var $time = $('.time', $controls);
			var updateTime = function() {
				
				var status = player.getStatus();
				var totalSecs = (status) ? status.time : 0;	
				
				var min = Math.floor(totalSecs / 60);
				var sec = Math.floor(totalSecs) - (min * 60);
				min = (min >= 10) ? min : "0" + min;
				sec = (sec >= 10) ? sec : "0" + sec;
				
				$time.text(min + ":" + sec);
			};
			
			//	Bind control buttons
			$('.red-btn', $controls).bind(
				'click',
				function(e) {
					if (playlist != RadioPlaylist) {
						playlist = RadioPlaylist;
						playlist.play(player);
						$controls.trigger('radio-on');
					}
					else if (!player.isPlaying() || player.getClip() == null) {
						playlist.resume(player);
						$controls.trigger('radio-on');
					}
					else {
						playlist.pause(player);
						$controls.trigger('radio-off');
					}
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			$('.next', $controls).bind(
				'click',
				function (e) {
					playlist.nextTrack(player);
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			$('.prev', $controls).bind(
				'click',
				function (e) {
					playlist.prevTrack(player);
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			$('.play-pause', $controls).bind(
				'click',
				function (e) {
					playlist.togglePlayPause(player);
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			var listSlideDown = function(callback) {
				//	Prevent firefox weird issue with sliding an element having overflow:auto
				$('.radio-bar-list-content').css('overflow', 'hidden');
				
				$('.radio-bar-list', $controls).slideDown(
					'slow',
					function() {
						//	Revert fix
						$('.radio-bar-list-content').css('overflow', 'auto');
						if (callback) {
							callback();
						}
					}
				);
			};
			
			var listSlideUp = function(callback) {
				//	Prevent firefox weird issue with sliding an element having overflow:auto
				$('.radio-bar-list-content').empty().css('overflow', 'hidden');
				
				$('.radio-bar-list', $controls).removeClass('favourites-avail').removeClass('tracklist-avail').removeClass('schedule-avail').slideUp(
					'slow',
					function() {
						//	Revert fix
						$('.radio-bar-list-content').css('overflow', 'auto');
						if (callback) {
							callback();
						}
					}
				);
			}
			
			var imageSlideUp = function() {
				$('.profile-image-avail', $controls).slideUp('slow');
			}
			
			var imageSlideDown = function() {
				$('.profile-image-avail', $controls).slideDown('slow');
			}
			
			//	Bind profile image button
			$('.profile-btn', $controls).bind('click',
				function (e) {
					if (!!$('.profile-image-avail:visible', $controls).length) {				
						imageSlideUp();		
					}
					else {
						listSlideUp();
						imageSlideDown();
					}
					
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			
			//	Bind tracklist button
			$('.chart', $controls).bind('click',
				function (e) {
				
					var track = playlist.currentTrack();
					var tracklistUrl = TrackHelper.tracklistUrl(track);
				
					if (!tracklistUrl || !!$('.tracklist-avail:visible', $controls).length) {
						listSlideUp();		
					}
					else if (!!$('.radio-bar-list:visible', $controls).length) {
						listSlideUp(
							function() { 
								$('.chart', $controls).trigger('click'); 
							} 
						);
					}
					else {
						imageSlideUp();
						listSlideDown();
						$('.radio-bar-list', $controls).addClass('tracklist-avail');
						$('.radio-bar-list-content', $controls).html('<h4>Loading...</h4>').load(tracklistUrl);
					}
					
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			//	Bind my favourites mixtapes button
			$('.playlist', $controls).bind('click',
				function (e) {
					
					var favouritesUrl = '/user_favourites/mixtapes';
				
					if (!favouritesUrl || !!$('.favourites-avail:visible', $controls).length) {
						listSlideUp();		
					}
					else if (!!$('.radio-bar-list:visible', $controls).length) {
						listSlideUp(
							function() { 
								$('.playlist', $controls).trigger('click'); 
							} 
						);
					}
					else {
						imageSlideUp();
						listSlideDown();
						$('.radio-bar-list', $controls).addClass('favourites-avail');
						$('.radio-bar-list-content', $controls).html('<h4>Loading...</h4>').load(favouritesUrl);
					}
					
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);

			//	Bind schedule button
			$('.schedule', $controls).bind('click',
				function (e) {

					var scheduleUrl = '/radio/latest';

					if (!!$('.schedule-avail:visible', $controls).length) {
						listSlideUp();
					}
					else if (!!$('.radio-bar-list:visible', $controls).length) {
						listSlideUp(
							function() {
								$('.schedule', $controls).trigger('click');
							}
						);
					}
					else {
						imageSlideUp();
						listSlideDown();
						$('.radio-bar-list', $controls).addClass('schedule-avail');
						$('.radio-bar-list-content', $controls).html('<h4>Loading...</h4>').load(scheduleUrl);
					}

					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
			
			//	Bind mp3 links
			$('a[rel$=.mp3]').live(
				'click',
				function(e) {
					var $this = $(this);
					
					var model = $this.attr('id').match(/^[^0-9]+/);
					var id = $this.attr('id').match(/\d+/);
					
					var track = {
						model: model,
						id: id,
						url: $this.attr('rel'),
						title: $this.attr('title'),
						artist: $this.attr('artist')
					};
					playlist.setPlaylist([track]);
					playlist.play(player);
					e.preventDefault();
					e.stopPropagation();
					return false;
				}
			);
		});

	};

})(jQuery);
