/**
 * @fileOverview This file contains the Views pertaining to the Radio 
 * @author Jacob Fierro
 */

/**
	@namespace
*/
var VV = {};
	VV.Radio = {};
	VV.Radio.Views = {};
	VV.Radio.Models = {};
	VV.Radio.Collections = {};




/*=========================================
	TRACK DISPLAY
==========================================*/

VV.Radio.Views.TrackTitle = Backbone.View.extend({
	el : $('#track_title'),
	template : _.template( $('#tmpl_track_title').html() ),

	initialize : function() {
		this.model.bind('change:trackTitle', this.render, this);
	},

	render : function() {
		// log('*TrackTitle: render: model: ', this.model.get('trackId'), this.model.get('trackTitle') );
		this.el.text( this.template( this.model.toJSON() ) ).hide().fadeIn();
	}
});

VV.Radio.Views.TrackPerformer = Backbone.View.extend({
	el : $('#track_performer'),
	template : _.template( $('#tmpl_track_performer').html() ),

	initialize : function() {
		this.model.bind('change:trackPerformer', this.render, this);
	},

	render : function() {
		this.el.text( this.template( this.model.toJSON() ) );
	}
});

VV.Radio.Views.TrackWindow = Backbone.View.extend({
	el : $('#info-window'),
	events : {
		"click #track_list" : "trackListControlClick"
	},

	initialize : function() {
		VV.Radio.Views.trackTitle = new VV.Radio.Views.TrackTitle({
			model : this.model
		});
		VV.Radio.Views.trackTitle.render();

		VV.Radio.Views.trackPerformer = new VV.Radio.Views.TrackPerformer({
			model : this.model
		});
		VV.Radio.Views.trackPerformer.render();
	},

	trackListControlClick : function() {
		this.trigger('click:trackListControl');
	}
});



/*=========================================
	CONTROLS
==========================================*/

VV.Radio.Views.Controls = Backbone.View.extend({
	el : $('.controls'),
	events : {
		"click #play_toggle" : "playToggle",
		"click #next" : "nextTrack",
		"click #previous" : "previousTrack",
		"mousedown .control" : "mouseDown",
		"mouseup .control" : "mouseUp" 
	},

	initialize : function() {		
		// toggle the play/pause graphic
		this.model.bind('change:isPlaying', this.playButtonImageToggle, this);
	},

	/**
	* Updates the model when user clicks the play/pause btn
	*/
	playToggle : function() {
		if (!this.model.get('isPlaying')) {
			this.model.set({ isPlaying : true });
		} else {
			this.model.set({ isPlaying : false });
		}
	},

	/**
	* Changes the play/pause button image on model change event
	*/
	playButtonImageToggle : function() {
		if (this.model.get('isPlaying')) {
			$('#play_toggle').removeClass('play').addClass('pause');
		} else {
			$('#play_toggle').removeClass('pause').addClass('play');
		}
	},

	/**
	* Set model.trackId to the next track in the set of tracks
	*/
	nextTrack : function() {
		var next = this.collection.getNextTrackId( this.model.get('trackId') );
		this.model.setNewTrack(next);
	},

	/**
	* Set model.trackId to the track before the current track in the set of tracks, this is not a 'history' functionality
	*/
	previousTrack : function() {
		var prev = this.collection.getPreviousTrackId( this.model.get('trackId') );
		this.model.setNewTrack(prev);
	},
	
	mouseDown : function(e) {
		$( "#"+$(e.currentTarget).attr('id') ).addClass('down');
	},

	mouseUp : function(e) {
		$( "#"+$(e.currentTarget).attr('id') ).removeClass('down');
	}

});



/*=========================================
	TRACK LIST
==========================================*/

VV.Radio.Views.TrackList = Backbone.View.extend({
	el : $('#tracklist'),
	ulElement : $('#list-wrapper ul'),
	template : _.template( $('#trackListItem-template').html() ),
	events : {
		"click .track a" : "trackSelection"
	},

	initialize : function() {
		this.collection.each(function(model) {
			this.ulElement.append( this.template( model.toJSON() ) );
		}, this);

		VV.Radio.Views.trackWindow.bind('click:trackListControl', this.showToggle, this);
	},

	showToggle : function() {
		this.el.slideToggle(300, function(){
			// stuff
		});
		$('#track_list').toggleClass('active');
	},

	trackSelection : function(e, v) {
		e.preventDefault();
		this.model.setNewTrack( $(e.currentTarget).attr('value') );
		this.showToggle();
	}
});



/*=========================================
	MAIN
==========================================*/

VV.Radio.Views.Main = Backbone.View.extend({
	el : $('#radio'),

	initialize : function() {
		
		VV.Radio.Collections.tracks = new VV.Radio.Collections.Tracks;
		VV.Radio.Collections.tracks.fetch({
			// data has loaded, commence with initializing the rest of the app
			success : function(collection, response) {
				VV.Radio.Views.main.dataHasInitialized();
			},

			// todo: make a safe fallback should the data not load
			error : function(collection, response) {
				log('*tracks: error: ', response);
			}
		});		
	},


	/**
	* This happens after the ajax data call, time to initialize all dependencies.
	*/
	dataHasInitialized : function() {
		this.collection = VV.Radio.Collections.tracks;

		// radio model keeps track of what the user is experiencing
		VV.Radio.Models.radio = new VV.Radio.Models.Radio({ collection : VV.Radio.Collections.tracks });
		this.model = VV.Radio.Models.radio; // this view uses the radio model heavily
				
		// View: Controls
		VV.Radio.Views.controls = new VV.Radio.Views.Controls({
			collection : VV.Radio.Collections.tracks,
			model : VV.Radio.Models.radio
		});

		
		// View: TrackWindow
		VV.Radio.Views.trackWindow = new VV.Radio.Views.TrackWindow({
			model : VV.Radio.Models.radio
		});
		

		// View: TrackList
		VV.Radio.Views.trackList = new VV.Radio.Views.TrackList({
			collection : VV.Radio.Collections.tracks,
			model : VV.Radio.Models.radio
		});


		// using this method to manually draw dom node because player.setSrc does not work on flash fallback browsers
		this.setTrackSource({ silent:true });


		// BIND TO EVENTS
		// I decided that the "main" radio view should own the media vs. any one sub view
		// as all subview influence the media and have equal right. The subview interfaces with
		// the media via the models, which we bind to here. 
		this.model.bind('change:isPlaying', this.playMedia, this);
		this.model.bind('change:trackId', this.setTrackSource, this);
	},


	/**
	* Will play or pause depending on current state of isPlaying in this.model
	*/
	playMedia : function() {
		if (this.model.get('isPlaying')) {
			this.me.play();
		} else {
			this.me.pause();
		}
	},


	/**
	* Gives a simple interface to pausing the media
	*/
	pauseMedia : function() {
		this.model.set({ isPlaying : false });
	},


	drawAudioNode : function() {
		var path = this.collection.getTrackPath( this.model.get('trackId') );
		var tag = '<audio id="audio_element" src="' +path+ '"></audio>';
		$('#audio-wrapper').html(tag);
	},

	/**
	* mediaelement player will not let you simply setSrc on flash fallback browsers, sadly.
	* Here we are testing browser's ability to play mp3's natively first,
	* and redrawing the dom node and creating a new instance of VV.Radio.mediaElement if it doesn't.
	* See: https://github.com/johndyer/mediaelement/issues/246#issuecomment-2059384
	* param {Object} opt Looking for {silent: true/false}, this determines if we autoplay
	*/
	setTrackSource : function(opt) {
		opt || (opt = {});

		if (!opt.silent) {this.model.set({isPlaying: false});}
		
		if ( !this.me ) {
			// we're initializing
			this.drawAudioNode();
			this.createMediaElement({ silent:true });
		} else {
			// we're changing tracks
			if (this.model.get('nativeMp3')) { 
				// html5 audio elements support setSrc (woot)
				this.me.setSrc( this.collection.getTrackPath( this.model.get('trackId') ) );
			} else {
				// mediaelement.js errors out on non-html5 audio element's, need to redraw every time
				this.drawAudioNode();
				this.createMediaElement({ silent:false });
			}
		}

		if (!opt.silent) {this.model.set({isPlaying: true});}
	},

	/*
	* Creates the mediaelement object, wiping the slate clean so to speak
	* @param {Boolean} silent Whether we auto play when mediaelement is created
	*/
	createMediaElement : function(opt) {
		opt || (opt = {});
		var view = this;
		// MediaElementPlayer is our hook into html5 audio api with a flash fallback
		VV.Radio.mediaElement = new MediaElementPlayer('#audio_element', {
			// the order of controls you want on the control bar (and other plugins below)
		    features: ['current','progress','duration'],
		    audioWidth: 340,
		    audioHeight: 8,
		    startVolume: 1,
		    // iPadUseNativeControls: false,
		    success : function(me, dom) {
		    	me.load();
		    	// the new dom el will error with "does not have method play" on flash fallbacks. 
		    	// if silent==false is passed in we know this is from a song selection event and should start
		    	// playing. We do not autoplay when we first initialize.
		    	// hopefully mediaelement.js will fix these issues eventually.
		    	if (!opt.silent) {
			    	me.play();
			    }			    
		    }
		});
		this.me = VV.Radio.mediaElement;
	}
});























