/// @author: Deepend


	/**
	 * Media Player Controls
	 */
	var RadioPlayerControl = base2.Base.extend({
		constructor: function(options) {
			this.SetOptions(options);
			this.LoadTemplates();
			this.SetEvents();
			this.Init();

		},
		
		Defaults: {
			MixtapeID:				null,

			Container: 				"#radio-bar",
			Panel:					".panel",
			Body:					".body",
			Trigger:				".panel .bar .trigger",
			PlayerID:				"player",
			MixtapeHost:			"http://staging.pulseradio.net",
			
			ContainerLoading:		".loading",
			PulsationElement:		".pulsation",
			MixtapeLoadingElement:	".mixtape-loading",
			
			ContainerArtist:		".artist",
			ContainerArtistImage:	".artist-image .image",
			
			
			ContainerTracks:		".tracks",
			TrackMenuItemSelector:	".menu li",
			TrackGroupSelector:		".group",
			
			ButtonShare:			".share.button",
			ButtonPlay:				".play.button",
			ButtonFavourite:		".favourite.button",
			
			ContainerActions:		".actions",
			
			ContainerAuthentication:".authentication",
			ContainerLoginForm:		"#radio_login",
			RadioUsernameInput:		"#player_username",
			RadioPasswordInput:		"#player_password",
			RadioLoginSubmit:		"#player_login_submit",
			ContainerSiteLoginForm:	"form[action='/users/login']",
			LoginUsernameInput:		"input[name='data[User][email]']",
			LoginPasswordInput:		"input[name='data[User][pass]']",

			MixtapeShareQueryVar:	"mixtape",
			ContainerSharing:		".actions div.sharing.panel",
			ShareLinkInput:			"input.embed-link",
			ShareLinkShortenButton: ".embed-link-shorten", // either the span or img, don't care.
			ShareEmbedInput:		"input.embed-code",
			ShareButtonTwitter:		".button.share-twitter",
			ShareButtonFacebook:	".button.share-facebook",
			ShareButtonMySpace:		".button.share-myspace",
			ShareButtonStumbleUpon: ".button.share-stumbleupon",
			
			APIPathBase:			"/web_services",
			APITimeout:				10000 /* milliseconds, :. 10 seconds */,
			
			TemplateScheduleItem:	"/templates/tracklist_schedule_item.html"
		},

		Loaded: false,

		Options: {},

		Templates: {},

		Container: null,
		Body: null,
		Trigger: null,

		// The full User object, eg. User.id, User.first_name, etc.
		User: null,
		
		// The current playing mixtape ID
		Current: null,

		// Currently-loaded schedule
		ScheduleMixtapes: null,
		

		Init: function() {
			this.HideControls();
			this.SetTrackGroup("schedule");
			this.ShowAction("login");
			this.LoadSchedule();
			
			// if mixtape specified, load it. Else load the schedule
			if (this.Options.MixtapeID != null) {
				this.SetMedia(this.Options.MixtapeID);
			} else {
				// If we have a schedule, load the first tape.
				// Pause after loading.
				if (this.ScheduleMixtapes instanceof Array && this.ScheduleMixtapes.length) {
					if (this.ScheduleMixtapes[0].Mixtape) {
						this.SetMedia(this.ScheduleMixtapes[0].Mixtape.id, true);
					}
				}
			}
			
			// Check if user is logged in
			this.CheckUser();
		},
		
		// Perform the remaining API calls
		LoadRemaining: function() {
			if (!this.Loaded) {
				this.Loaded = true;
				this.LoadRelatedMixtapes();
				
				if (this.User) {
					this.LoadMixtapeHistory(this.User.id);
					this.LoadFavouriteMixtapes(this.User.id);
				}

				this.SetMixtapeProfileImage(this.Artist);
				
				// Open to Recommended
				this.SetTrackGroup("recommended");
			}
		},

		SetOptions: function(options) {
			this.Options = jQuery.extend({}, this.Defaults, options);
			this.Container = jQuery(this.Options.Container);
		},

		SetEvents: function() {
			
			// Trigger
			this.Container.find(this.Options.Trigger).click(jQuery.proxy(function(event) {
				var trigger = jQuery(event.currentTarget);
				
				// Open or close the controls
				var body = this.Container.find(this.Options.Body);
				if (body.hasClass("closed")) {
					if (!this.Loaded) {
						this.LoadRemaining();
					}
					this.ShowControls();
				} else {
					this.HideControls();
				}

			}, this));

			// Tracks Menu
			this.Container.find(this.Options.ContainerTracks).delegate(this.Options.TrackMenuItemSelector, "click", jQuery.proxy(function(event) {
				var menuItem = jQuery(event.currentTarget);

				this.SetTrackGroup(menuItem.attr("rel"));
			}, this));

			// Track actions - PLAY
			this.Container.find(this.Options.ContainerTracks).delegate(this.Options.ButtonPlay, "click", jQuery.proxy(function(event) {
				
				var playItem = jQuery(event.currentTarget);
				var playID = playItem.attr("rel");
				this.SetMedia(playID);

			}, this));

			//Track actions - FAVOURITE
			this.Container.find(this.Options.ContainerTracks).delegate(this.Options.ButtonFavourite, "click", jQuery.proxy(function(event) {
				var favouriteItem = jQuery(event.currentTarget);
				var favouriteID = favouriteItem.attr("rel");

				// Will ask the API, or throw up a login box.
				this.AddFavourite(favouriteID);

			}, this));

			// Track actions - SHARE
			this.Container.find(this.Options.ContainerTracks).delegate(this.Options.ButtonShare, "click", jQuery.proxy(function(event) {
				var trigger = jQuery(event.currentTarget);

				// Set up and show share links
				// TODO: Brittle reference to the data
				this.PopulateShareURLs(trigger.parent().parent().data('mixtape'));
				this.ShowAction("share");
				
				
			}, this));
			
			
			// URL Shortening Button
			this.Container.find(this.Options.ContainerSharing).delegate(this.Options.ShareLinkShortenButton, "click", jQuery.proxy(function(event){
				var container = this.Container.find(this.Options.ContainerSharing);
				var targetInput = container.find(this.Options.ShareLinkInput);
				var urlToShorten = targetInput.val();
				targetInput.addClass('loading');
				targetInput.val(''); // clear the box

				var apiHandler = new APIHandler({
					Url: '/web_services/bitly_shorten',
					Method: APIMETHODS.GET,
					Data: { url_to_shorten: urlToShorten },
					Async: true,
					Callback: jQuery.proxy(function(response){
						targetInput.removeClass('loading');
						if (response.result && response.value.url != undefined) {
							targetInput.val(response.value.url);
						}
					}, this)
				});

			}, this));

			
			// Login Submit
			this.Container.find(this.Options.ContainerLoginForm).delegate(this.Options.RadioLoginSubmit, "click", jQuery.proxy(function(event) {
				var submit = jQuery(event.currentTarget);

				this.Login();

				return false;
			}, this));
			
			
			
			// TODO: Refactor all three?
			
			/** SITE PLAY BUTTONS **/
			jQuery("body").delegate("a.play, .mixtapes-list .mixtape .play-icon, .tracklist .play a, .schedule-list .entry .play-icon2, .profile-mixtapes .play .play-trigger, .schedule-list .play-icon", "click", jQuery.proxy(function(event) {

				var item = jQuery(event.currentTarget);

				this.ParsePlayElement(item);

				return false;
			}, this));
			
			/** **/
			jQuery("body").delegate(".mod-mixtapes .mixtape .btn-play", "click", jQuery.proxy(function(event) {
				var trigger = jQuery(event.currentTarget);
				var item = trigger.parent();
				
				this.ParsePlayElement(item);
				
				return false;
			}, this));
			
			/** PODCAST BUTTONS **/
			/*
			// DISABLE PODCAST BUTTONS
			jQuery("body").delegate(".music-podcast a.play-icon", "click", jQuery.proxy(function(event) {
				var item = jQuery(event.currentTarget);
				this.ParsePlayElement(item);
				return false;
			}, this));
			*/
			
		},
		
		ParsePlayElement: function(element) {
			var trackUrl = element.attr("rel");
			var artist = element.attr("artist") ? element.attr("artist") : "Pulse Radio";
			var title = element.attr("title");
			
			//console.log(artist + ": " + title + " - " + trackUrl);
			
			// Determine what type of link this is,
			// and strip out the type and ID.
			// Sample mixtape: /mixtapes/download/1051.mp3
			// Sample podcast: /media/podcasts/25.mp3
			var matches = (/^\/mixtapes\/download\/([0-9]+)\.mp3/).exec(trackUrl);
			if (matches && matches.length > 1 && matches[1]) {
				// It's a mixtape.
				this.SetMedia(matches[1]);
			} else {
				/*
				// DISABLE: Podcast Play buttons
				matches = (/^\/media\/podcasts\/([0-9]+)\.mp3/).exec(trackUrl);
				if (matches && matches.length > 1 && matches[1]) {
					alert('Podcast #'+matches[1]);
				}
				*/
			}
		},
		
		LoadTemplates: function() {
                        // Hacked so this works correctly on nginx
			//this.Templates.ScheduleItem = LoadFile(this.Options.TemplateScheduleItem);
			this.Templates.ScheduleItem = '<li><div class="track-actions"><div class="share button"></div><div class="play button"></div><a class="follow-channel-med"><span class="follow-channel-message"></span></a></div><span class="time"></span><div class="title"><span class="artist-name"></span></div></li>';
		},
		
		/// Main function to set a mixtape to play.
		/// Also sets artist information and share links
		SetMedia: function(mixtapeID, pauseOnLoad) {
			
			this.Pulsate();
			this.PauseOnLoad = pauseOnLoad;
			
			// Get the Mixtape data.
			var mixtape = this.API_GetMixtape(mixtapeID, jQuery.proxy(this.GetMixtapeHandler, this));
			
		},
		
		GetMixtapeHandler: function(response) {
 
			mixtape = response.value;
			
			this.Current = mixtape;
			this.CurrentID = mixtape.Mixtape.id;

			var mixtapeUrl = Site.fullBaseUrl + "/mixtapes/expose/" + mixtape.Mixtape.id + ".mp3";

			// determine mixtape location
			var mixtapeLocation = new APIHandler({
				Url: mixtapeUrl,
				Method: APIMETHODS.GET,
				Async: true,
				Callback: jQuery.proxy(this.SetMixtapeHandler, this)
			});
			
			
			// Check if streaming
			if ((/^\//).test(mixtapeLocation.Value)) {
				mixtapeLocation.Value = "http://pulseradio.net" + mixtapeLocation.Value;
			}
			//console.log(mixtapeLocation.Value);

		},
		
		SetMixtapeProfileImage: function(artist) {
			var artistName;
			if (artist) {
				var artistContainer = this.Container.find(this.Options.ContainerArtist);
				artistID = artist.Profile.id;
				artistName = artist.Profile.title;
				artistContainer.find("h5").show().html(artist.Profile.title);
				artistContainer.find(".description").html(artist.Profile.content_summary);

			
				// Only call the Profile Image when radio bar is fully loaded
				if (this.Loaded) {
					// Get the artist profile image
					this.API_GetProfileImage(artistID, jQuery.proxy(this.GetProfileImageHandler, this));
				}
				
			} else { // no artist information available. just show track
				var artistContainer = this.Container.find(this.Options.ContainerArtist);
				artistName = "";
				artistContainer.find("h5").hide().html("");
				artistContainer.find(".description").html("");
				
				this.Container.find(this.Options.ContainerArtistImage).empty().hide();
			}
			
			return artistName;
		},
		
		SetMixtapeHandler: function(response) {
			
			// Force pauseOnLoad to boolean
			pauseOnLoad = !!this.PauseOnLoad;
			
			mixtapeLocation = response;
			
			var mixtape = this.Current;
			
			// Populate the button and copy-paste share URL box
			var shareUrl = this.PopulateShareURLs(mixtape);
			
			var artistName;
			var trackName = mixtape.Mixtape.title;
			var duration = mixtape.Mixtape.duration;
			var mixtapeUrl = Site.fullBaseUrl + "/mixtapes/expose/" + mixtape.Mixtape.id + ".mp3";
			

			
			

			// Set the artist information
			var artist = mixtape.RelatedArtist[0];
			this.Artist = artist;
			artistName = this.SetMixtapeProfileImage(artist);
			

			// Get related mixtapes . Only if radiobar is fully loaded;
			if (this.Loaded) {
				this.LoadRelatedMixtapes();
			}
			
			
			// Check if streaming
			if ((/^\//).test(mixtapeLocation.Value)) {
				mixtapeLocation.Value = "http://pulseradio.net" + mixtapeLocation.Value;
			}
			
			// Setup the flash player
			var flashPlayer = this.GetFlashPlayerObject();
			
			// flashPlayer.setMedia(shareUrl, artistName, trackName, mixtapeUrl, duration, startPlay);
			flashPlayer.setMedia(shareUrl, artistName, trackName, mixtapeLocation.Value, duration, !pauseOnLoad );
			
			// Load/reload the history now we've just told the server
			// we're playing a track
			if (this.User && this.Loaded) {
				this.LoadMixtapeHistory(this.User.id);
			}
		},

		
		GetFlashPlayerObject: function() {
			var flashPlayer = getFlashMovieObject(this.Options.PlayerID);
			
			return flashPlayer;
		},
		
		
		GetProfileImageHandler: function(response) {
			
			if (response.result) {
				this.Container.find(this.Options.ContainerArtistImage).empty().html(response.value.ProfileImage).show();
			}
			
		},

	
		/// hides the player controls
		HideControls: function() {
			var body = this.Container.find(this.Options.Body);
			body.stop(true, false).animate({ height: 0, paddingTop: 0 });
			body.addClass("closed");
			this.Container.find(this.Options.Trigger).removeClass("down");
		},
		
		/// shows the player controls
		ShowControls: function() {
			var body = this.Container.find(this.Options.Body);
			body.stop(true, false).animate({ height: 260, paddingTop: 10 } );
			body.removeClass("closed");
			this.Container.find(this.Options.Trigger).addClass("down");	
		},
		
		ToggleControls: function() {
			var body = this.Container.find(this.Options.Body);
			if (body.hasClass("closed")) {
				this.ShowControls();
			} else {
				this.HideControls();
			}
			
		},
		
		ShowAction: function(action) {
			var actionsContainer = this.Container.find(this.Options.ContainerActions);
			
			var panels = actionsContainer.find(".panel");
			panels.slideUp();			
			
			switch (action) {
				case "share":
				case "sharing":
					var target = actionsContainer.find(".sharing.panel");
					target.slideDown();
					break;
				case "login":
				case "authenticate":
				case "authentication":
					var target = actionsContainer.find(".authentication.panel");
					target.slideDown();
					break;
			}
		},
		
		/// sets the active track group
		SetTrackGroup: function(group) {
			this.Container.find(this.Options.TrackMenuItemSelector).removeClass("active");
			
			var menuItem = this.Container.find(this.Options.TrackMenuItemSelector + "[rel=" + group + "]");
			
			menuItem.addClass("active");
			
			// find the group
			this.Container.find(this.Options.TrackGroupSelector).removeClass("active").hide();
			var groupElement = this.Container.find(this.Options.TrackGroupSelector +"[data-id=" + group + "]");
			groupElement.stop(true, false).show().addClass("active");
		},
		

		PopulateShareURLs: function(mixtape) {

			var liveUrl = 'http://pulseradio.net';

			// Calculate the Share URL, track name and artist from the mixtape object.
			// Build up the base of the Share URL
			var shareUrl = "";
			with (window.location) {
				shareUrl = protocol+"//"+host;
			}

			var artistName = 'Pulse Radio';
			var trackName = mixtape.Mixtape.title;

			if (mixtape.RelatedArtist != undefined) {
				// Sometimes RelatedArtist is an array.
				// Sometimes it isn't.
				var artist;
				if (mixtape.RelatedArtist instanceof Array && mixtape.RelatedArtist[0] != undefined) {
					artist = mixtape.RelatedArtist[0];
				} else {
					artist = mixtape.RelatedArtist;
				}
					
				// Does the artist have a page?
				// (If not, the link will just default to the home page)
				if (artist.Profile != undefined) {
					// eg. "http://pulseradio.net/artists/martin-landsky"
					shareUrl += artist.Profile.url;
					artistName = artist.Profile.title;
				}
			}

			// Add our mixtape query var 
			// eg. "http://pulseradio.net/artists/martin-landsky?mixtape=8051"
			shareUrl += '?'+encodeURIComponent(this.Options.MixtapeShareQueryVar)+'='+encodeURIComponent(mixtape.Mixtape.id);


			// Link textbox
			this.Container.find(this.Options.ShareLinkInput).val(shareUrl);

			// Embed textbox
			// TODO: Convert downloadUrl to exposed Url
			var downloadUrl = liveUrl + '/mixtapes/download/' + mixtape.Mixtape.id + '.mp3';

			var exposeResponse = this.API_ExposeMixtape(mixtape.Mixtape.id);
			downloadUrl = exposeResponse.Value; 
			var embedSrc = 'http://pulseradio.net/swf/facebook/share_player.swf?mediaUrl=' + escape(downloadUrl)
				+ '&title=' + encodeURIComponent(trackName)
				+ '&artist=' + encodeURIComponent(artistName)
				+ '&shareUrl=' + encodeURIComponent(shareUrl)
				+ '&startPlay=false'
				+ '&trackDuration=' + encodeURIComponent(mixtape.Mixtape.duration);
			this.Container.find(this.Options.ShareEmbedInput).val('<object width="400" height="82"><param name="movie" value="'+embedSrc+'" /><param name=quality value=high /><embed src="'+embedSrc+'" quality=high pluginspage="http://..../index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="400" height="82"></embed></object>');


			// Share buttons
			var container = this.Container;
			var setButtonUrl = function(buttonSelector, shareUrl) {
				var button = container.find(buttonSelector+" a");
				button.attr('href', shareUrl);
			}

			// TODO: Do we want the artist name?
			var title = trackName;
			if (artistName != undefined) {
				title += " ("+artistName+")";
			}

			with (this.Options) {
				setButtonUrl(ShareButtonTwitter, "http://twitter.com/share?url="+encodeURIComponent(shareUrl)+"&text="+encodeURIComponent(title));
				setButtonUrl(ShareButtonFacebook, "http://facebook.com/sharer.php?u="+encodeURIComponent(shareUrl));
				setButtonUrl(ShareButtonMySpace, "javascript:void(window.open('http://www.myspace.com/Modules/PostTo/Pages/?u="+escape(shareUrl)+"),'ptm','height=450,width=550').focus())");
				setButtonUrl(ShareButtonStumbleUpon, "http://stumbleupon.com/submit?url="+encodeURIComponent(shareUrl));
			}

			return shareUrl;
		},
		
		
		Pulsate: function() {
			
			var loadingContainer = this.Container.find(this.Options.ContainerLoading);
			var pulse = loadingContainer.find(this.Options.PulsationElement);
			
			var loadingWidth = loadingContainer.width();
			var pulseWidth = pulse.width();
			
			pulse.css({ left: -pulseWidth});
			
			pulse.animate({ left: loadingWidth}, 1500, "easeInOutCubic")
				.animate({ left: -pulseWidth}, 1, "easeInOutCubic")
				.animate({ left: loadingWidth}, 1500, "easeInOutCubic")
				.animate({ left: -pulseWidth}, 1, "easeInOutCubic")
				.animate({ left: loadingWidth}, 1500, "easeInOutCubic")

			var mixtapeLoading = this.Container.find(this.Options.MixtapeLoadingElement);
			var mixtapeLoadingText = mixtapeLoading.find("span");
			mixtapeLoading.css({opacity: 0}).animate({opacity: 1}, 500);
			mixtapeLoadingText.animate({ opacity: 1 }, 500)
				.animate({ opacity: 0}, 500)
				.animate({ opacity: 1}, 500)
				.animate({ opacity: 0}, 500, "swing", function() { mixtapeLoading.animate({ opacity: 0}, 500)});
		},

/** Interactivity **/

		// Twiddles all the dials and sets up all the panels after we've
		// got a user that the back-end's confirmed to be logged in.
		// Used by CheckUser() and LoginHandler().
		SetLoggedIn: function(user) {
			//console.log(user);

			// Now logged in
			this.User = user;

			// Get rid of the login panel
			this.Container.find(this.Options.ContainerAuthentication).slideUp();

			// Set up the favourites and history panels
			if (this.Loaded) {
				this.LoadFavouriteMixtapes(user.id);
				this.LoadMixtapeHistory(user.id);
			}

			//this.API_GetFavourites(user.id, jQuery.proxy(this.API_GetFavouritesHandler, this));
			//this.API_GetMixtapeHistory(user.id, jQuery.proxy(this.API_GetMixtapeHistoryHandler, this));
			
			//Set the favourited elements so we can traverse through the dom and change any icons to show the user
			followed_channels = this.User.favourites.profiles;
			favourited_mixtapes = this.User.favourites.mixtapes;
			favourited_articles = this.User.favourites.articles;
			
			
			//See if we can find the a href that has a corresponding rel="" tag e.g. rel="favourite_mixtape/9254">
			for (x in favourited_mixtapes)
			{
				$('a.follow-channel-small[rel="favourite_mixtape/'+favourited_mixtapes[x]+'"]').css('background-position','0px -18px');
				$('a.follow-channel-med[rel="favourite_mixtape/'+favourited_mixtapes[x]+'"]').css('background-position','-69px 0px');
			}
			for (x in followed_channels)
			{
				$('a.follow-channel[rel="follow_channel/'+followed_channels[x]+'"]').css('background-position','0px -47px');
			}
			for (x in favourited_articles)
			{
				$('a.follow-channel-med[rel="favourite_article/'+favourited_articles[x]+'"]').css('background-position','-69px 0px');
			}
		},


		
		LoadSchedule: function() {
			var group = "recommended";
			
			var scheduleResponse = this.API_GetFeaturedMixtapes();
			//this.ScheduleMixtapes = scheduleResponse.value.ScheduleMixtape;
			this.ScheduleMixtapes = scheduleResponse.value;
			
			// Clear out current mixtapes
			var limit = 5;
			this.ClearGroup(group);

			base2.Array2.forEach(this.ScheduleMixtapes, jQuery.proxy(function(mixtape) {
				if (limit > 0) {
					this.LoadMixtapeIntoGroup(group, mixtape, jQuery(this.Templates.ScheduleItem));
					limit --;
				}
			}, this));
			
		},
		
		LoadRelatedMixtapes: function() {
			
			var relatedResponse = this.API_GetRelatedMixtapes(this.CurrentID, jQuery.proxy(this.LoadRelatedMixtapesHandler, this));

		},
		
		LoadRelatedMixtapesHandler: function(response) {
			var relatedMixtapes = response.value;

			var group = "related";			
			var limit = 5;
			this.ClearGroup(group);
			
			base2.Array2.forEach(relatedMixtapes, jQuery.proxy(function(mixtape) {
				if (limit > 0) {
					this.LoadMixtapeIntoGroup(group, mixtape, jQuery(this.Templates.ScheduleItem));
					limit --;
				}
			}, this));
		},
		
		LoadFavouriteMixtapes: function(userID) {
			var response = this.API_GetFavourites(userID, jQuery.proxy(function(response){
				var group = "favourite";
				this.ClearGroup(group);
				if (response.result) {
					this.LoadMixtapesIntoGroup(group, response.value.Mixtape, this.Templates.ScheduleItem, 5);
				} else {
					// TODO: Set blank, "no favourites", etc?
				}
			}, this));
		},

		LoadMixtapeHistory: function(userID) {
			var response = this.API_GetMixtapeHistory(userID, jQuery.proxy(function(response){
				var group = "history";
				this.ClearGroup(group);
				if (response.result) {
					this.LoadMixtapesIntoGroup(group, response.value, this.Templates.ScheduleItem, 5);
				} else {
					// TODO: Set blank, "no favourites", etc?
				}
			}, this));
		},

		LoadMixtapesIntoGroup: function(group, mixtapes, itemTemplateHTML, limit) {
			base2.Array2.forEach(mixtapes, jQuery.proxy(function(mixtape) {
				if (limit > 0) {
					this.LoadMixtapeIntoGroup(group, mixtape, itemTemplateHTML);
					limit --;
				}
			}, this));
		},


/** Generic Tracklisting **/
		LoadMixtapeIntoGroup: function(group, mixtape, itemTemplate) {
			var groupContainer = this.Container.find(this.Options.TrackGroupSelector + "." + group + " ul");
			var template = jQuery(itemTemplate);
			
			if (mixtape.RelatedArtist && mixtape.RelatedArtist.Profile) {
				template.find(".artist-name").html(mixtape.RelatedArtist.Profile.title);
			}
			if (mixtape.Profile) {
				template.find(".artist-name").html(mixtape.Profile.title);
			}
			
			if (mixtape.Mixtape != undefined) {
				template.find(".title").append(mixtape.Mixtape.title);
				template.find(".time").html(SecondsToMinutes(mixtape.Mixtape.duration))
				template.find(".play").attr({rel: mixtape.Mixtape.id});
				template.find(".follow-channel-med").attr({rel: 'favourite_mixtape/'+mixtape.Mixtape.id});
				template.data("mixtape", mixtape);
			}
			
			groupContainer.append(template);
		},
		
		ClearGroup: function(group) {
			var groupContainer = this.Container.find(this.Options.TrackGroupSelector + "." + group + " ul");
			groupContainer.empty();
		},
		
		
/** User Session **/

		CheckSession: function() {
			
			this.API_GetCurrentUser(jQuery.proxy(this.CheckSessionHandler, this));	
			
		},
		
		CheckSessionHandler: function(response) {
			
			if (response.result) {
				
			} else {
				
			}
		},
		

		CheckUser: function() {
			
			if (window.pulse_user) {
				this.User = window.pulse_user;
				if (window.pulse_user.Loaded) {
					this.SetLoggedIn(window.pulse_user.User);
				} else {
				
					this.ClearGroup("history");
					this.ClearGroup("favourite");
				}
				
				this.ClearGroup("history");
				this.ClearGroup("favourite");
			}
		},
		
		Login: function() {
			
			var username = this.Container.find(this.Options.ContainerLoginForm).find(this.Options.RadioUsernameInput).val();
			var password = this.Container.find(this.Options.ContainerLoginForm).find(this.Options.RadioPasswordInput).val();
			
			if (username != "" && password != "") {
				var data = {
					"data": {
						"User":{"email": username,"pass": password }
					}
				};

				var apiHandler = new APIHandler({
					Url: "/web_services/authenticate",
					Method: APIMETHODS.POST,
					Data: data, 
					Callback: jQuery.proxy(this.LoginHandler, this)
				});
			}

		},
		
		LoginHandler: function(response) {
			if (response.result) {
				// logged in ;)
				this.SetLoggedIn(response.value.User);
			} else {
				// TODO: could not log in
				// TODO: Make everything red?
			}
		},

		
		AddFavourite: function(mixtapeID) {
			if (this.User) {
				// We're logged in; make the API call.
				// The backend checks if we're actually logged in or not.
				this.API_AddFavourite(mixtapeID, jQuery.proxy(function(response){
					if (response.result) {
						// Reload the favourites list to keep up to date
						this.LoadFavouriteMixtapes(this.User.id);
					} else {
						// TODO: No idea.
					}
				}, this));

			} else {
				// Not logged in; pop up the login dialog
				this.ShowAction("login");
			}
		},
		
		
/** API CALLS **/

		API_GetFeaturedMixtapes: function() {
			var apiHandler = new APIHandler({
				Url: "/web_services/featured_mixtapes",
				Method: APIMETHODS.GET
			});
			
			return apiHandler.Response;
		},

		API_GetSchedule: function() {
			var apiHandler = new APIHandler({
				Url: "/web_services/schedule/currently_playing",
				Method: APIMETHODS.GET
			});
			
			return apiHandler.Response;
		},
		
		API_GetMixtape: function(mixtapeID, callback) {

			var apiHandler = new APIHandler({
				Url: "/web_services/get_mixtape/" + mixtapeID,
				Method: APIMETHODS.GET,
				Async: true,
				Callback: callback
			});
			
			return apiHandler.Response;
		},
		
		API_ExposeMixtape: function(mixtapeID, callback) {
			
			var apiHandler = new APIHandler({
				Url: "/mixtapes/expose/" + mixtapeID + ".mp3",
				Method: APIMETHODS.GET,
				Async: false,
				Callback: callback
			});
			
			return apiHandler.Response;
		},
		
		API_GetRelatedMixtapes: function(mixtapeID, callback) {
			var apiHandler = new APIHandler({
				Url: "/web_services/related_mixtapes/" + mixtapeID,
				Method: APIMETHODS.GET,
				Async: true,
				Callback: callback
			});
			
			return apiHandler.Response;
		},
		
		API_GetMixtapeHistory: function(userID, callback) {
			var data = {
				user_id: userID
			}
			
			var apiHandler = new APIHandler({
				Url: "/web_services/mixtape_history",
				Method: APIMETHODS.GET,
				Data: data,
				Async: true,
				Callback: callback
			});
			
			return apiHandler.Response;
		},
		
		API_GetCurrentUser: function(callback) {
			
			var apiHandler = new APIHandler({
				Url: "/web_services/get_current_user",
				Method: APIMETHODS.GET,
				Callback: callback,
				Async: true
			});
			
			return apiHandler.Response;
			
		},
		
		API_GetFavourites: function(userID, callback) {

			var data = {
				user_id: userID
			}

			var apiHandler = new APIHandler({
				Url: "/web_services/user_favourites",
				Method: APIMETHODS.GET,
				Data: data,
				Async: true,
				Callback: callback
			});
			
			return apiHandler.Response;
		},
		

		API_AddFavourite: function(mixtapeID, callback) {

			// API handles checking if the user is logged in
			var apiHandler = new APIHandler({
				// API doesn't like query vars
				Url: "/web_services/user_favourite_add/mixtape/"+encodeURIComponent(mixtapeID),
				Method: APIMETHODS.GET,
				Async: true,
				Callback: callback
			});
			
			return apiHandler.Response;
		},

		
		API_GetProfileImage: function(profileID, callback) {
			
			var apiHandler = new APIHandler({
				Url: "/web_services/get_profile_image/" + profileID + "/132x132",
				Method: APIMETHODS.GET,
				Async: true,
				Callback: callback
			});
			
			return apiHandler.Response;
		}

		
	})

	
	
/** GLOBAL FUNCTIONS **/
	
	function SecondsToMinutes(seconds) {
		var minutes = parseInt(seconds / 60);
		var seconds = seconds % 60;
		
		var time = minutes + ":" + PadDigits(seconds, 2);
		
		return time;
	}	
	
	function ShareHandler() {
		jQuery.proxy(function(){
			this.ShowControls();
			if (this.Current) {
				this.ShowAction("share");
			}
		}, radioPlayerControl)();
	}
	
	
	function FavouriteHandler() {
		jQuery.proxy(function(){
			this.ShowControls();
			if (this.CurrentID) {
				this.AddFavourite(this.CurrentID);
				this.SetTrackGroup("favourite");
			}
		}, radioPlayerControl)();
	}


	function getFlashMovieObject(movieName){
		if (window.document[movieName]){
			return window.document[movieName];
		}
		if (navigator.appName.indexOf("Microsoft Internet")==-1){
			if (document.embeds && document.embeds[movieName])
				return document.embeds[movieName];
		}
		else{
			return document.getElementById(movieName);
		}
	}
	
		
	/**
	* Loads the specified template
	* @param {Object} templateUrl
	*/
	function LoadFile(url) {
	    var file;
	
	    file = jQuery.ajax({
	        url: url,
	        type: "GET",
	        async: false
	    });
	
	    return file.responseText;
	}
	
	/**
	* 
	* @param {Object} name
	*/
	function getParameterByName(name) {
	    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
	    var regexS = "[\\?&]" + name + "=([^&#]*)";
	    var regex = new RegExp(regexS);
	    var results = regex.exec(window.location.href);
	    if (results == null)
	        return "";
	    else
	        return decodeURIComponent(results[1].replace(/\+/g, " "));
	}
	
	
	
    function PadDigits(n, totalDigits) 
    { 
        n = n.toString(); 
        var pd = ''; 
        if (totalDigits > n.length) 
        { 
            for (i=0; i < (totalDigits-n.length); i++) 
            { 
                pd += '0'; 
            } 
        } 
        return pd + n.toString(); 

    } 

