/*
  Half-way done JS mp3 player. It's a mess right now, but it will be cleaned up.
  Author: Kris Hedstrom (based on a demo script found at http://schillmania.com/projects/soundmanager2/)
  Requires SoundManager 2 Javascript API + jQuery

*/

GY.audio = function() {
  var self = this;
  var pl = this;
  var sm = soundManager; // soundManager instance
  this.excludeClass = 'dl'; // CSS class for ignoring MP3 links
  this.links = [];
  this.sounds = [];
  this.soundsByURL = [];
  this.indexByURL = [];
  this.lastSound = null;
  this.soundCount = 0;
  var isIE = (navigator.userAgent.match(/msie/i));

  this.config = {
    playNext: true, // stop after one sound, or play through list until end
	autoPlay: false  // start playing the first sound right away
  };

  this.css = {
    // CSS class names appended to link during various states
    sDefault: 'audio-link', // default state
    sLoading: 'audio-loading',
    sPlaying: 'audio-playing',
    sPaused: 'audio-paused'
  };

  this.addEventHandler = function(o,evtName,evtHandler) {
    typeof(attachEvent)=='undefined'?o.addEventListener(evtName,evtHandler,false):o.attachEvent('on'+evtName,evtHandler);
  };

  this.removeEventHandler = function(o,evtName,evtHandler) {
    typeof(attachEvent)=='undefined'?o.removeEventListener(evtName,evtHandler,false):o.detachEvent('on'+evtName,evtHandler);
  };

  this.classContains = function(o,cStr) {
	return (typeof(o.className)!='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false);
  };

  this.addClass = function(o,cStr) {
    if (!o || !cStr || self.classContains(o,cStr)) return false;
    o.className = (o.className?o.className+' ':'')+cStr;
  };

  this.removeClass = function(o,cStr) {
    if (!o || !cStr || !self.classContains(o,cStr)) return false;
    o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');
  }

  this.getSoundByURL = function(sURL) {
    return (typeof self.soundsByURL[sURL] != 'undefined'?self.soundsByURL[sURL]:null);
  }

  this.isChildOfNode = function(o,sNodeName) {
    if (!o || !o.parentNode) {
      return false;
    }
    sNodeName = sNodeName.toLowerCase();
    do {
      o = o.parentNode;
    } while (o && o.parentNode && o.nodeName.toLowerCase() != sNodeName);
    return (o.nodeName.toLowerCase() == sNodeName?o:null);
  }

	this.events = {

		// handlers for sound events as they're started/stopped/played
	
		onload: function() {
			var totalTime = $(this._data.oLink).siblings('div.time').children('div.total-time');
			totalTime.text(self.getTime(self.getDurationEstimate(this), true));
			var loading = $(this._data.oLink).siblings('div.audio-track').children('div.loading');
			loading.fadeOut();
		},
	
		play: function() {
			$('.active-player').removeClass('active-player');
			var lnk = $(this._data.oLink);
			var parent = lnk.parent();
			parent.addClass('active-player');
			var progressBar = lnk.siblings('div.audio-track').children('div.progress');
			var elapsed = lnk.siblings('div.time').children('div.elapsed');
			progressBar.css({'width': '0%'});
			elapsed.text('0:00');
			pl.removeClass(this._data.oLink,this._data.className);
			this._data.className = pl.css.sPlaying;
			pl.addClass(this._data.oLink,this._data.className);
	    },

		stop: function() {
			pl.removeClass(this._data.oLink,this._data.className);
			this._data.className = '';
	    },

		pause: function() {
			pl.removeClass(this._data.oLink,this._data.className);
			this._data.className = pl.css.sPaused;
			pl.addClass(this._data.oLink,this._data.className);
	    },

	    resume: function() {
			pl.removeClass(this._data.oLink,this._data.className);
			this._data.className = pl.css.sPlaying;
			pl.addClass(this._data.oLink,this._data.className);      
	    },

		finish: function() {
			var parent = $(this._data.oLink).parent();
			if(self.links.length > 1) {
				parent.removeClass('active-player');
				pl.removeClass(this._data.oLink,this._data.className);
				this._data.className = '';
				if (pl.config.playNext) {
					var nextLink = (pl.indexByURL[this._data.oLink.href]+1);
					if (nextLink<pl.links.length) {
						pl.handleClick({'target':pl.links[nextLink]});
					}
				}
			}

		},
    
		whileplaying: function() {
			self.updateTime.apply(this);
	    },
    
		whileloading: function() {
			var loading = $(this._data.oLink).next('div.audio-track').children('div.loading');
			$('.loading').hide();
			if(loading) {
				loading.show();
			}
		}
	};

	this.stopEvent = function(e) {
		if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
			e.preventDefault();
		} else if (typeof event != 'undefined' && typeof event.returnValue != 'undefined') {
			event.returnValue = false;
		}
		return false;
	};

	this.getTheDamnLink = (isIE)?function(e) {
		// I really didn't want to have to do this.
		return (e && e.target?e.target:window.event.srcElement);
		}:function(e) {
		return e.target;
	};

	this.handleClick = function(e) {
		// a sound link was clicked
		if (typeof e.button != 'undefined' && e.button>1) {
			// ignore right-click
			return true;
		}
		var o = self.getTheDamnLink(e);
		if (o.nodeName.toLowerCase() != 'a') {
			o = self.isChildOfNode(o,'a');
			if (!o) return true;
		}
		var sURL = o.getAttribute('href');
		if (!o.href || !o.href.match(/\.mp3(\\?.*)$/i) || self.classContains(o,self.excludeClass)) {
			if (isIE && o.onclick) {
				return false; // IE will run this handler before .onclick(), everyone else is cool?
			}
			return true; // pass-thru for non-MP3/non-links
		}

		var soundURL = (o.href);
		var thisSound = self.getSoundByURL(soundURL);
		if (thisSound) {
			// already exists
			if (thisSound == self.lastSound) {
				// and was playing (or paused)
				thisSound.togglePause();
			} else {
				// different sound
				thisSound.togglePause(); // start playing current
				sm._writeDebug('sound different than last sound: '+self.lastSound.sID);
				if (self.lastSound) self.stopSound(self.lastSound);
			}
		} else {
			// create sound
			thisSound = sm.createSound({
				id:'inlineMP3Sound'+(self.soundCount++),
				url:soundURL,
				onload:self.events.onload,
				onplay:self.events.play,
				onstop:self.events.stop,
				onpause:self.events.pause,
				onresume:self.events.resume,
				onfinish:self.events.finish,
				whileplaying:self.events.whileplaying,
				whileloading:self.events.whileloading
		 });
		// tack on some custom data
		thisSound._data = {
		oLink: o, // DOM node for reference within SM2 object event handlers
			className: self.css.sPlaying
		};
		self.soundsByURL[soundURL] = thisSound;
		self.sounds.push(thisSound);
		if (self.lastSound) self.stopSound(self.lastSound);
			thisSound.play();
			// stop last sound
		}

		self.lastSound = thisSound; // reference for next call

		if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
			e.preventDefault();
		} else {
		 	event.returnValue = false;
		}
		return false;
	};

	this.stopSound = function(oSound) {
		soundManager.stop(oSound.sID);
		soundManager.unload(oSound.sID);
	};

	this.getTime = function(nMSec,bAsString) {
	   // convert milliseconds to mm:ss, return as object literal or string
	   var nSec = Math.floor(nMSec/1000);
	   var min = Math.floor(nSec/60);
	   var sec = nSec-(min*60);
	   // if (min == 0 && sec == 0) return null; // return 0:00 as null
	   return (bAsString?(min+':'+(sec<10?'0'+sec:sec)):{'min':min,'sec':sec});
	 };

	this.updateTime = function() {
		var timex = self.getTime(this.position, true);
		var elapsed = $(this._data.oLink).siblings('div.time').children('div.elapsed');
		var totalTime = $(this._data.oLink).siblings('div.time').children('div.total-time');
		var progress = $(this._data.oLink).next('div.audio-track').children('div.progress');
		elapsed.text(timex);
		totalTime.text(self.getTime(self.getDurationEstimate(this), true));
		progress.css({'width': ((this.position/self.getDurationEstimate(this))*100)+'%'});
	};

	this.getDurationEstimate = function(oSound) {
		if (oSound.instanceOptions.isMovieStar) {
			return (oSound.duration);
		} else {
			return (!oSound._data.metadata || !oSound._data.metadata.data.givenDuration?oSound.durationEstimate:oSound._data.metadata.data.givenDuration);
		}
	};


	this.createElements = function(el, selected) {
		var audioPlayer = $('<div class="audio-player"/>')
		if (selected) {
			audioPlayer.addClass('active-player'); 
		}

		var audioTrack = $('<div class="audio-track"/>');
		var progress = $('<div class="progress"/>');
		var loading = $('<div class="loading"/>').hide();
		audioTrack.append(progress).append(loading); 
		
		el.wrap(audioPlayer);
		
		var audioTime = $('<div class="time"/>');
		var audioElapsed = $('<div class="elapsed"/>').text('-:--');
		var divider = $('<div/>').text(' / ');
		var audioTotalTime = $('<div class="total-time"/>').text('-:--');
		
		audioTime.append(audioElapsed).append(divider).append(audioTotalTime);

		el.after(audioTime).after(audioTrack);
	};

	this.init = function() {
		var oLinks = $('a.audio');
		// grab all links, look for .mp3
		var foundItems = 0;
		for (var i = 0, l = oLinks.length; i<l; i++) {
			if (oLinks[i].href.match(/\.mp3/i) && !self.classContains(oLinks[i],self.excludeClass)) {
				$(oLinks[i]).addClass(self.css.sDefault);
				if(i === 0) {
					self.createElements($(oLinks[i]), true);
				} else {
					self.createElements($(oLinks[i]), false);
				}
				self.links[foundItems] = (oLinks[i]);
				self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing
				foundItems++;
			}
		}
		if (foundItems>0) {
			self.addEventHandler(document,'click',self.handleClick);
			if (self.config.autoPlay) {
				self.handleClick({target:self.links[0],preventDefault:function(){}});
			}
		}
	};
	
	this.init();

};

//var audio = null;

soundManager.debugMode = false; // disable or enable debug output

soundManager.url = rootTemplateVirtual + '/_ui/swf/'; // path to directory containing SM2 SWF

soundManager.onready(function() {
	if (soundManager.supported()) {
	// soundManager.createSound() etc. may now be called
		var audio = new GY.audio();
	}
});
