var flashSound;

var FlashSound = function(config){
  
  var master = this;
  var flashElement;
  var jElement = $("#flashSound");
  var flashId = "flashSoundReplace";
  var on = true;
  var readyQueue = new Array();
  var playQueue = new Array();
  var currentVolume = null;
  var currentSound = null;
  
  var STATE_SOUND_STOPPED = 0;
  var STATE_SOUND_FADEIN = 1;
  var STATE_SOUND_PLAYING = 2;
  var STATE_SOUND_FADEOUT = 3;
  var STATE_SOUND_DISABLED = 4;
  var SOUND_FADE_IN_TIME = 4000;
  var SOUND_FADE_OUT_TIME = 2000;
  var SOUND_TICK_DELAY = 200;
  var currentState = null;
  
  this.init = function(){
    
    var flashvars = {};
    var flashparams = { allowScriptAccess:"always", bgcolor:"#170b0e" };
    var attributes = {id:flashId, name:flashId};
    swfobject.embedSWF("/flash/sound.swf", flashId, "1", "1", "9.0.0", null, flashvars, flashparams, attributes);
    
    /* We are currently playing no sound */
    this.next(STATE_SOUND_STOPPED);
  };
  
  this.flashReady = function(){
    
    var soundManager = this;
    
    if(flashElement == null){
      flashElement = $("#"+flashId).get(0);

      $(jElement).attr("class","on");

      /* Repeatedly do tick events */
      var wait = setInterval(function() {

        soundManager.tick();
        
      }, SOUND_TICK_DELAY);
    }
  };
  
  this.next = function( state ){

    var soundManager = this;

    currentState = state;
    
    switch( currentState ){
      
      case STATE_SOUND_STOPPED:
        break;
        
      case STATE_SOUND_FADEIN:
        /* If the sound player is ready */
        if(flashElement && flashElement.playSound) {
          if(playQueue.length > 0){
            /* Get the newest sound in the queue */
            var sound = playQueue[playQueue.length - 1];
            /* Clear the queue because we only care about the newest */
            playQueue = new Array();
            /* Play the sound */
            currentSound = sound.sound;
            soundManager.setVolume(0);
            flashElement.playSound(sound.sound);
          }
        }
        break;
        
      case STATE_SOUND_PLAYING:
        break;
        
      case STATE_SOUND_FADEOUT:
        break;
        
      case STATE_SOUND_DISABLED:
        break;
        
      default:
        /* ?? This should never happen! */
        window.alert("Error in flash sound state machine!");
        break;
    }
  };
  
  this.tick = function(){

    var soundManager = this;
    
    /* Do any queued ready callbacks if sound is enabled */
    if(currentState != STATE_SOUND_DISABLED){
      for(i = 0; i < readyQueue.length; i++){
        var callback = readyQueue.pop();
        callback();
      }
    }
    
    switch( currentState ){
      
      case STATE_SOUND_STOPPED:
        if(playQueue.length > 0){
          soundManager.next(STATE_SOUND_FADEIN);
        }
        break;
        
      case STATE_SOUND_FADEIN:
        if(currentVolume < 1){
          var increment = SOUND_TICK_DELAY/SOUND_FADE_IN_TIME
          soundManager.setVolume(currentVolume + increment);
        }else{
          soundManager.next(STATE_SOUND_PLAYING);
        }
        break;
        
      case STATE_SOUND_PLAYING:
        break;
        
      case STATE_SOUND_FADEOUT:
        if(currentVolume > 0){
          var decrement = SOUND_TICK_DELAY/SOUND_FADE_OUT_TIME
          soundManager.setVolume(currentVolume - decrement);
        }else{
          soundManager.next(STATE_SOUND_STOPPED);
        }
        break;
        
      case STATE_SOUND_DISABLED:
        if(currentVolume > 0){
          var decrement = SOUND_TICK_DELAY/SOUND_FADE_OUT_TIME
          soundManager.setVolume(currentVolume - decrement);
        }
        break;
        
      default:
        /* ?? This should never happen! */
        window.alert("Error in flash sound state machine!");
        break;
    }
    
  };
  
  this.disable = function(){
    var soundManager = this;
    soundManager.next(STATE_SOUND_DISABLED);
  }
  
  this.enable = function(){
    var soundManager = this;
    soundManager.next(STATE_SOUND_FADEIN);
  }
  
  this.play = function( sound ){
    
    /* Ignore if the sound is already playing */
    if(currentSound == sound){
      return;
    }
    
    var soundManager = this;
    
    var playRecord = {
      sound: sound,
      fadein: null, //Deprecated
      fadeout: null //Deprecated
    };
    
    playQueue.push(playRecord);
    
    switch( currentState ){
      
      case STATE_SOUND_STOPPED:
        break;
        
      case STATE_SOUND_FADEIN:
          soundManager.next(STATE_SOUND_FADEOUT);
        break;
        
      case STATE_SOUND_PLAYING:
          soundManager.next(STATE_SOUND_FADEOUT);
        break;
        
      case STATE_SOUND_FADEOUT:
        break;
        
      case STATE_SOUND_DISABLED:
        break;
        
      default:
        /* ?? This should never happen! */
        window.alert("Error in flash sound state machine!");
        break;
    }
  };
  
  this.setVolume = function( vol ){
    
    if(vol == null || vol < 0){
      vol = 0;
    }
    
    currentVolume = vol;
    
    if(!on){
      return;
    }
    
    if(flashElement && flashElement.setVolume) {
      flashElement.setVolume(vol);
    }else{
    }
  };
  
  this.waitReady = function(callback){
    
    /* If the callback is not a function then there is nothing to notify when ready */
    if(callback == null || typeof(callback) != 'function'){
      return;
    }
    
    /* If ready, execute callback immediately */
    if( flashElement != null ){
      callback();
    }
    /* Otherwise add callback to queue */
    else{
      readyQueue.push(callback);
    }
  };
  
  this.soundOn = function(){
    on = true;
    $(jElement).attr("class","on");
    if(flashElement && flashElement.turnSoundOn) flashElement.turnSoundOn();
  };
  
  this.soundOff = function(){
    on = false;
    $(jElement).attr("class","");
    if(flashElement && flashElement.turnSoundOff) flashElement.turnSoundOff();
  };
  
  jElement.click(function(){
    if (on){
      master.soundOff();
    } else {
      master.soundOn();
    }
    return false;
  });
  
  this.init();
  
}