/*
 *            __
 *     ____  / /___ ___  ______ _
 *    / __ \/ / __ `/ / / / __ `/
 *   / /_/ / / /_/ / /_/ / /_/ /
 *  / .___/_/\__,_/\__, /\__,_/
 * /_/            /____/
 *  
 * - a jQuery plugin for SoundManager 2
 * by Klaus Dahlén & Aarni Koskela at Anders Inno Oy, MMXI
 *
 * Licensed under the MIT License:
 * 
 * Copyright (C) 2011 by Anders Inno Oy
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 */


(function($){
	function humanizeMilliseconds(ms) {
		var s = Math.floor(ms / 1000);
		var m = Math.floor(s / 60);
		var rs = s % 60;
		
		if(rs < 10) rs = "0" + rs;
		
		return m + ":" + rs;
	}
		
	var Playa = function($el) {
		var self = this;
		this.$el = $el;
		
		this.soundIsLoading = function(){
			self.$player.addClass("loading");
		};
		
		this.soundOnLoad = function(){
			self.$player.removeClass("loading");
		};
		
		this.$player = $el;
		this.$playpause = $(".playpause", this.$player);
		this.$mute = $(".mute", this.$player);
		this.$volume = $(".volume", this.$player);
		this.$time = $(".time", this.$player).hide();
		this.$currentVolume = $(".current-volume", this.$player);
		this.$progressBg = $(".progress-bg", this.$player);
		this.$progressBar = $(".progress-bar", this.$player);
		this.$progressBuffer = $(".progress-buffer", this.$player);
		this.sound = null;
		this.load = function(url) {
			if(this.sound) this.unload();
			this.sound = soundManager.createSound({
				id:			"s" + (+new Date()),
				url:		url,
				autoPlay:	false,
				whileloading: this.soundIsLoading,
				onload: this.soundOnLoad
			});
		};
		
		this.unload = function() {
			if(this.sound) {
				this.sound.stop();
				this.sound = null;
			}
		};
		
		this.play = function() {
			if(this.sound) {
				this.sound.play();
				this.updateState();
			}
		};
		
		this.updateState = function() {
			if(!this.sound) {
				this.$progressBar.hide();
			} else {
				var duration = this.getDurationEstimate();
				var position = this.sound.position;
				var progress = position / duration * 100;
				this.$progressBar.width(progress + "%");
				
				var stateClasses = [];
				if(this.sound.paused) stateClasses.push("is-paused");
				else if(this.sound.playState == 1) stateClasses.push("is-playing");
				
				if(this.sound.playState == 0) stateClasses.push("is-stopped");
				
				if(this.sound.muted) stateClasses.push("is-muted");
				
				this.$el.removeClass("is-playing is-paused is-stopped is-muted").addClass(stateClasses.join(" "));
				this.$progressBar.show();
				
				this.$progressBuffer.width(this.sound.bytesLoaded / this.sound.bytesTotal * 100 + "%");
				
				//this.$time.text(humanizeMilliseconds(this.sound.position));
			}
		};
		
		this.getDurationEstimate = function() {
			if (this.sound.isBuffering) {
				return this.sound.durationEstimate;
			}
			return this.sound.duration;
		};
		
		this.pause = function() {
			if(this.sound) {
				this.sound.pause();
				this.updateState();
			}
		};
		
		this.playPauseAction = function() {
			if(!this.sound) return;
			this.sound.togglePause();
			this.updateState();
		};
		
		this.muteAction = function() {
			if(!this.sound) return;
			this.sound.toggleMute();
			this.updateState();
		};
		
		this.seek = function(e) {
			if(!this.sound) return;
			var x = e.layerX;
			var width = $(e.currentTarget).width();
			var pos = x / width * this.sound.duration;
			
			this.sound.setPosition(pos);
			this.updateState();
		};
		
		this.setVolume = function(e) {
			if(!this.sound) return;
			var x = e.layerX;
			var width = $(e.currentTarget).width();
			var vol = Math.ceil(x / width * 100);
			
			this.sound.setVolume(vol);
			this.$currentVolume.width(vol + "%");
			this.updateState();
		};
		
		
		/* bindings */
		this.$playpause.click(function() {
			self.playPauseAction();
			return false;
		});
		
		this.$mute.click(function(){
			self.muteAction();
			return false;
		});
		
		this.$progressBg.click(function(e) {
			self.seek(e);
			return false;
		});
		
		this.$progressBg.mousemove(function(e){
			if(!self.sound || !self.sound.loaded) {
				return;
			}
			var x = e.layerX;
			if(!x) return;
			var width = $(e.currentTarget).width();
			var duration = self.getDurationEstimate();
			var pos = x / width * duration;
			
			self.$time.show().text(humanizeMilliseconds(pos));
			self.$time.css("left", x + 80); // note that this is hardcoded for the current project..
			
		}).mouseout(function(e){
			self.$time.hide();
		});
		//,
		//	function(e){
		//		self.$time.hide();
		//	}
		//);
		
		this.$volume.click(function(e) {
			self.setVolume(e);
			return false;
		});
		
		setInterval(function() { self.updateState(); }, 500);
	};
		
	/*	Create a new Playa. Returns a control object for it. If several elements are playa'd like this, the last control object will be returned.
		The control object can be acquired again by $("#el").playa().
	*/
	$.fn.playa = function(options) {
		var ret = null;
		this.each(function() {
			var $this = $(this);
			var playa = $this.data("playa");
			if(!playa) {
				playa = new Playa($this);
				$(this).data("playa", playa);
			}
			ret = playa;
		});
		return ret;
	};
}(jQuery));

