/*
  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 + Mootools

*/

function InlinePlayer() {
  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.getNext('div.time').getChildren('div.total-time')[0];
		if(totalTime) {
			totalTime.set('text', self.getTime(self.getDurationEstimate(this), true));
		}
		var loading = this._data.oLink.getNext('div.audio-track').getChildren('div.loading')[0];
		if(loading) {
			loading.fade('out'); //set('styles', {'display': 'none'});
			//$('loading').fade('in');
		}	
	},
	
    play: function() {
      $$('.active-player').removeClass('active-player');
      var parent = this._data.oLink.getParent();
      parent.addClass('active-player');
      var progressBar = this._data.oLink.getNext('div.audio-track').getChildren('div.progress')[0];
      var elapsed = this._data.oLink.getNext('div.time').getChildren('div.elapsed')[0];
      if(progressBar) {
      	progressBar.set('styles', {'width': '0%'});
      }	
      if(elapsed) {
      	elapsed.set('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() {
      //$$('.active-player').removeClass('active-player');
      var parent = this._data.oLink.getParent();
      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() {
      //soundManager._writeDebug('sound '+this.sID+' playing, '+this.position+' of '+this.duration);
      //var d = null;
      //d = new Date();
      //if (d-self.lastWPExec>500) {
      
      self.updateTime.apply(this);
      //}
      //self.lastWPExec = d;
      
    },
    
	whileloading: function() {
	   var loading = this._data.oLink.getNext('div.audio-track').getChildren('div.loading')[0];
	   $$('.loading').set('styles', {'display': 'none'});
	   if(loading) {
	   		loading.set('styles', {'display': 'block'});
	   }
	}
    
    

  }

  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
    }
    sm._writeDebug('handleClick()');
    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() {
		//console.log(self);
		var timex = self.getTime(this.position, true);
		var elapsed = this._data.oLink.getNext('div.time').getChildren('div.elapsed')[0];
		var totalTime = this._data.oLink.getNext('div.time').getChildren('div.total-time')[0];
		var progress = this._data.oLink.getNext('div.audio-track').getChildren('div.progress')[0];
		if(elapsed) {
			elapsed.set('text', timex);
			totalTime.set('text', self.getTime(self.getDurationEstimate(this), true));
		}
		if(progress) {
			progress.set('styles', {'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) {
		if (selected) {
			var audioPlayer = new Element('div', {'class': 'audio-player active-player'}); 
		}
		else {
			var audioPlayer = new Element('div', {'class': 'audio-player'}); 
		}
		var audioTrack = new Element('div', {'class': 'audio-track'});
		var progress = new Element('div', {'class': 'progress'});
		var loading = new Element('div', {'class': 'loading', 'styles': {'display': 'none'}});
		audioTrack.grab(progress).grab(loading); 
		
		var audioTime = new Element('div', {'class': 'time'});
		var audioElapsed = new Element('div', {'class': 'elapsed', 'text': '-:--'});
		var divider = new Element('div', {'text': ' / '});
		var audioTotalTime = new Element('div', {'class': 'total-time', 'text': '-:--'});
		audioTime.grab(audioElapsed).grab(divider).grab(audioTotalTime); 
		
		audioPlayer.wraps(el);
		el.grab(audioTime, 'after');
		el.grab(audioTrack, 'after');
	}

  this.init = function() {
    sm._writeDebug('inlinePlayer.init()');
    //var oLinks = document.getElementsByTagName('a');
    //var oLinks = $$('a.play-audio');
    //var divs = $$('div#audio-player');
    var oLinks = $$('a.audio');
    // grab all links, look for .mp3
    var foundItems = 0;
    for (var i=0, j=oLinks.length; i<j; 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(){}});
	  }
    }
    sm._writeDebug('inlinePlayer.init(): Found '+foundItems+' relevant items.');
  }
	
  	this.init();

}

var inlinePlayer = null;

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

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

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