/*
  Breakbit inline media
  Based upon the SoundManager 2 Demos
  ----------------------------------------------
  http://schillmania.com/projects/soundmanager2/
  Requires SoundManager 2 Javascript API.
*/

function initBreakbitPlayer(oConfigOverride) {
  var self = this;
  var pl = this;
  var sm = soundManager; // soundManager instance
  this.excludeClass = 'inline-exclude'; // CSS class for ignoring MP3 links
  this.links = [];
  this.strings = [];
  this.sounds = [];
  this.soundsByURL = [];
  this.indexByURL = [];
  this.lastSound = null;
  this.soundCount = 0;

  this.lastWPExec = new Date();
  var isIE = (navigator.userAgent.match(/msie/i));

  this.config = {
    flashVersion: 9,        // version of Flash to tell SoundManager to use - either 8 or 9. Flash 9 required for peak / spectrum data.
    useMovieStar: true,    // Flash 9.0r115+ only: Support for a subset of MPEG4 formats.
    useHighPerformance: false,    // Blah
    useHTML5Audio: true,    // Blah
    useVideo: true,         // show video when applicable
    usePeakData: false,     // [Flash 9 only]: show peak data
    useWaveformData: false, // [Flash 9 only]: enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.
    useEQData: true,       // [Flash 9 only]: enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.
    fillGraph: false,       // [Flash 9 only]: draw full lines instead of only top (peak) spectrum points
    useThrottling: false,    // try to rate-limit potentially-expensive calls (eg. dragging position around)
    autoStart: (window.location.href.toString().match(/autoplay=1/i)?true:false),       // begin playing first sound when page loads
    playNext: true,         // stop after one sound, or play through list until end
    emptyTime: '',      // null/undefined timer values (before data is available)
    useFavIcon: false,
  }

  this._mergeObjects = function(oMain,oAdd) {
    // non-destructive merge
    var o1 = {}; // clone o1
    for (var i in oMain) {
      o1[i] = oMain[i];
    }
    var o2 = (typeof oAdd == 'undefined'?{}:oAdd);
    for (var o in o2) {
      if (typeof o1[o] == 'undefined') o1[o] = o2[o];
    }
    return o1;
  }

  if (typeof oConfigOverride != 'undefined' && oConfigOverride) {
    // allow overriding via arguments object
    this.config = this._mergeObjects(oConfigOverride,this.config);
  }

  this.css = {
    // CSS class names appended to link during various states
    sDefault: 'sm2_link', // default state
    sLoading: 'sm2_loading',
    sPlaying: 'sm2_playing',
    sPaused: 'sm2_paused'
  }

  // apply externally-defined override, if applicable
  this.cssBase = []; // optional features added to ul.playlist
  if (this.config.usePeakData) this.cssBase.push('use-peak');
  if (this.config.useWaveformData || this.config.useEQData) this.cssBase.push('use-spectrum');
  this.cssBase = this.cssBase.join(' ');
  
  // apply some items to SM2
  sm.flashVersion = this.config.flashVersion;
  if (sm.flashVersion >= 9) {
    sm.useMovieStar = this.config.useMovieStar; // enable playing FLV, MP4 etc.
    sm.movieStarOptions.useVideo = this.config.useVideo;
    sm.defaultOptions.usePeakData = this.config.usePeakData;
    sm.defaultOptions.useWaveformData = this.config.useWaveformData;
    sm.defaultOptions.useEQData = this.config.useEQData;
  }

  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.hasClass = function(o,cStr) {
    return (typeof(o.className)!='undefined'?new RegExp('(^|\\s)'+cStr+'(\\s|$)').test(o.className):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.getElementsByClassName = function(className,tagNames,oParent) {
    var doc = (oParent||document);
    var matches = [];
    var i,j;
    var nodes = [];
    if (typeof(tagNames)!='undefined' && typeof(tagNames)!='string') {
      for (i=tagNames.length; i--;) {
        if (!nodes || !nodes[tagNames[i]]) {
          nodes[tagNames[i]] = doc.getElementsByTagName(tagNames[i]);
        }
      }
    } else if (tagNames) {
      nodes = doc.getElementsByTagName(tagNames);
    } else {
      nodes = doc.all||doc.getElementsByTagName('*');
    }
    if (typeof(tagNames)!='string') {
      for (i=tagNames.length; i--;) {
        for (j=nodes[tagNames[i]].length; j--;) {
          if (self.hasClass(nodes[tagNames[i]][j],className)) {
            matches[matches.length] = nodes[tagNames[i]][j];
          }
        }
      }
    } else {
      for (i=0; i<nodes.length; i++) {
        if (self.hasClass(nodes[i],className)) {
          matches[matches.length] = nodes[i];
        }
      }
    }
    return matches;
  }
  
  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.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.events = {

    // handlers for sound events as they're started/stopped/played

    play: function() {
      pl.removeClass(this._data.oLink,this._data.className);
      $(this._data.oLoading).animate({left:'0%', width:'0%', opacity:'1'},{queue:false,duration:1});
      $(this._data.oPosition).animate({left:'0%', width:'0%', opacity:'1'},{queue:false,duration:1});
      this._data.className = pl.css.sPlaying;
      pl.addClass(this._data.oLink,this._data.className);
      if (document.getElementById('sm2-movie-box')){
         document.getElementById('videohide').style.display = 'block';
         document.getElementById('sm2-movie-box').style.width = '0px';
         document.getElementById('sm2-movie-box').style.height = '0px';
         var sm = soundManager; sm.oMC.style.width = '0px'; sm.oMC.style.height = '0px'; 
      }
    },

    stop: function() {
      $(this._data.oLoading).animate({opacity:'0'},{queue:false,duration:200});
      $(this._data.oPosition).animate({opacity:'0'},{queue:false,duration:200});
      pl.removeClass(this._data.oLink,this._data.className);
      this._data.className = '';
      this._data.oTiming.innerHTML = '';

      if (document.getElementById('sm2-movie-box')){
         document.getElementById('videohide').style.display = 'block';
         document.getElementById('sm2-movie-box').style.width = '0px';
         document.getElementById('sm2-movie-box').style.height = '0px';
         var sm = soundManager; sm.oMC.style.width = '0px'; sm.oMC.style.height = '0px'; 
      }
    },

    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() {
      pl.removeClass(this._data.oLink,this._data.className);
      $(this._data.oLoading).animate({opacity:'0'},{queue:false,duration:400});
      $(this._data.oPosition).animate({opacity:'0'},{queue:false,duration:400});
      this._data.className = '';
      this._data.oTiming.innerHTML = '';

      if (document.getElementById('sm2-movie-box')){
         document.getElementById('albumpage_album').style.display = 'block';
         document.getElementById('sm2-movie-box').style.width = '0px';
         document.getElementById('sm2-movie-box').style.height = '0px';
         var sm = soundManager; sm.oMC.style.width = '0px'; sm.oMC.style.height = '0px'; 
      }

      if (pl.config.playNext) {
        var nextLink = (pl.indexByURL[this._data.oLink.href]+1);
        if (nextLink<pl.links.length) {
          pl.handleClick({'target':pl.links[nextLink]});
        }
      }
    },

    metadata: function() {
	// video-only stuff
        var sm = soundManager;
        // set the SWF dimensions to match
        thisHeight = 270;
	sm.oMC.style.height = thisHeight+'px';
        thisWidth = 270 * (this.width / this.height);
	sm.oMC.style.width = thisWidth+'px';

      if (document.getElementById('sm2-movie-box')){
          document.getElementById('videohide').style.display = 'none';
          document.getElementById('sm2-movie-box').style.width = thisWidth+'px';
          document.getElementById('sm2-movie-box').style.height = thisHeight+'px';
        }
    },

    whileloading: function() {
      if ((this.bytesLoaded/this.bytesTotal)<1){
        this._data.oLoading.style.width = (((this.bytesLoaded/this.bytesTotal)*100)+'%'); // theoretically, this should work.
      } else if (this._data.oLoading.style.opacity == "1"){
        this._data.oLoading.style.width = "100%";
        $(this._data.oLoading).animate({opacity:'0'},{queue:true,duration:500});
      }
      if (!this._data.didRefresh && this._data.metadata) {
        this._data.didRefresh = true;
        this._data.metadata.refresh();
      }
    },
	
    whileplaying: function() {
      var d = null;
          this._data.oPosition.style.width = (((this.position/self.getDurationEstimate(this))*100)+'%');
      if (pl.dragActive || !pl.config.useThrottling) {
        self.updateTime.apply(this);
  	    if (sm.flashVersion >= 9) {
          if (pl.config.usePeakData && this.instanceOptions.usePeakData) self.updatePeaks.apply(this);
	      if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {
	        self.updateGraph.apply(this);
	      }
	    }
        if (this._data.metadata) {
          d = new Date();
          if (d && d-self.lastWPExec>300) {
            self.refreshMetadata(this);
            self.lastWPExec = d;
          }
        }
      } else {
        d = new Date();
        if (d-self.lastWPExec>300) {
          self.updateTime.apply(this);
	      if (sm.flashVersion >= 9) {
            if (pl.config.usePeakData && this.instanceOptions.usePeakData) {
	          self.updatePeaks.apply(this);
	        }
	        if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {
		      self.updateGraph.apply(this);		      
		}
          }
          if (this._data.metadata) self.refreshMetadata(this);
          self.lastWPExec = d;
        }
      }
  }
}

  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 || !sm.canPlayURL(o.href) || 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,
       onplay:self.events.play,
       onstop:self.events.stop,
       onpause:self.events.pause,
       onresume:self.events.resume,
       onfinish:self.events.finish,
       whileloading:self.events.whileloading,
       whileplaying:self.events.whileplaying,
       onmetadata:self.events.metadata
      });

      // tack on some custom data
      thisSound._data = {
        oLink: o, // DOM node for reference within SM2 object event handlers		
        oPosition: self.getElementsByClassName('back_pos','div',o.parentNode.parentNode)[0],
        oLoading: self.getElementsByClassName('back_load','div',o.parentNode.parentNode)[0],
        oTiming: self.getElementsByClassName('time','span', o.parentNode.parentNode)[0],
        className: self.css.sPlaying
      };

      // set initial timer stuff (before loading)
      thisSound._data.oTiming.innerHTML = self.config.emptyTime;

      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.refreshMetadata = function(oSound) {
    // Display info as appropriate
    var index = null;
    var now = oSound.position;
    var metadata = oSound._data.metadata.data;
    for (var i=0, j=metadata.length; i<j; i++) {
      if (now >= metadata[i].startTimeMS && now <= metadata[i].endTimeMS) {
        index = i;
        break;
      }
    }
    if (index != metadata.currentItem) {
      // update
      metadata.currentItem = index;
    }
  }
    
  this.updateTime = function() {
    this._data.oTiming.innerHTML = self.getTime(this.position,true) + ' / ' + self.getTime(this.duration*(this.bytesTotal/this.bytesLoaded),true);
  }

  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.init = function() {
    sm._writeDebug('breakbitPlayer.init()');
    var oLinks = document.getElementsByTagName('a');
    // grab all links, look for .mp3
    var foundItems = 0;
    for (var i=0; i<oLinks.length; i++) {
      if (sm.canPlayURL(oLinks[i].href) && !self.hasClass(oLinks[i],self.excludeClass)) {
        self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration
        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.autoStart) {
	    self.handleClick({target:self.links[0],preventDefault:function(){}});
	  }
    }
    sm._writeDebug('breakbitPlayer.init(): Found '+foundItems+' relevant items.');
  }

  this.init();

}
 
soundManager.url = '/wp-includes/js/soundmanager/'; // path to directory containing SM2 SWF
var breakbitPlayer = new initBreakbitPlayer();

soundManager.debugMode = false; // disable or enable debug output

soundManager.onready(function() {
  if (soundManager.supported()) {
    breakbitPlayer.init();
  }
});