twaudio = (function() {
  var AudioPlayer = $.klass({
    initialize: function(audioPath, options) {
      this.options = options || {};
      
      if (typeof this.options.autoPlay == 'undefined') 
        this.options.autoPlay = true;  
          
      this.audioPath = audioPath;
      this.uuid = AudioPlayer.uuid++;
      this._createPlayer();
      this._buildControls();
    },
    _createPlayer: function() {
      $(document.body).append('<div></div>');
      this.player = $('div:last').attr('id', 'player_' + this.uuid);
      this.player.jPlayer({
        swfPath: '/swf',
        ready: $.bind(function() {
          this.player.setFile(this.audioPath);
          if (this.options.autoPlay) this.player.play();
        }, this)
      }).onProgressChange(function() {});
    },
    _buildControls: function() {
      var uuid = this.uuid;
      
      this.element.append($.build(function(h) {
        h.div(
          h.div({ id: 'play' + uuid, 'class' : 'player_play', title: 'Play Audio' }),
          h.div({ id: 'pause' + uuid, 'class' : 'player_pause', title: 'Pause Audio' }),
          h.div({ 'class' : 'player_progress' },
            h.div({ id: 'loaded' + uuid, 'class' : 'player_loaded' },
              h.div({ id: 'played' + uuid, 'class' : 'player_played' })
            )
          ),
          h.div({ id: 'time' + uuid, 'class' : 'player_time' }),
          h.div({ id: 'mute' + uuid, 'class' : 'player_mute' }),
          h.div({ id: 'volume' + uuid, 'class' : 'player_volume' , title: 'Adjust Volume' },
            h.div({ id: 'volume_value' + uuid, 'class' : 'player_volume_value' })
          )
        );
      }));
      
      this.player.jPlayerId('play', 'play' + uuid).
                  jPlayerId('pause', 'pause' + uuid).
                  jPlayerId('playBar', 'played' + uuid).
                  jPlayerId('loadBar', 'loaded' + uuid).
                  jPlayerId('volumeBar', 'volume' + uuid).
                  jPlayerId('volumeBarValue', 'volume_value' + uuid);
                  
      if (this.options.ready) this.options.ready.call(this);
    }
  });
  
  AudioPlayer.uuid = 0;
  
  var Uploader = $.klass({
    initialize: function(options) {
      this.uuid = Uploader.uuid++;
      this.options = options;
      
      this._buildUploader();
      
      this.swfupload = new SWFUpload({
        upload_url: options.uploadUrl,
        flash_url: options.flashUrl,
        button_placeholder_id: 'upload' + this.uuid,
        file_post_name: 'file',
        file_queue_limit: 1,
        file_upload_limit: 0,
        file_size_limit: '10 MB',
        http_success : [ 200, 201, 204 ],
        file_types: '*.mp3',
        file_types_description: 'MP3 Files',
        post_params: options.postParams,
        button_image_url: '/images/browse_btn.jpg',
        button_width: 108,
        button_height: 29,
        button_text: '',
        button_cursor : SWFUpload.CURSOR.HAND,
        button_window_mode : SWFUpload.WINDOW_MODE.TRANSPARENT, 
        file_queued_handler: $.bind(this._fileSelected, this),
        file_queue_error_handler: $.bind(this._handleError, this),
        file_dialog_start_handler: $.bind(this._clearDialog, this),
        upload_progress_handler: $.bind(this._uploadProgress, this),
        upload_success_handler: $.bind(function(file) {
          $('#sound_path').attr('value', this.options.uploadRoot + '/audio.mp3');
          $(this.form).find('input[type=submit]').attr('value', 'Saving...');
          this.form.submit();
        }, this),
        upload_error_handler: $.bind(this._uploadFailed, this)
      });
      
      this.form = this.element.parents('form').get(0);
      
      $(this.form).submit($.bind(function() {
        if (this.fileSelected) {
          var submit = $(this.form).find('input[type=submit]');
          $(submit).attr('value', 'Uploading...');
          $(this.form).find('input[type=submit]').attr('disabled', 'disabled');
          this.swfupload.startUpload();
        }
        return false;
      }, this));
    },
    _buildUploader: function() {
      var uuid = this.uuid;
      
      this.element.html($.build(function(h) {
        h.div({ 'class': 'uploader' },
          h.input({ id: 'file' + uuid, 'class': 'uploader_filename', readonly: 'readonly' }),
          h.div({ id: 'upload' + uuid }),
          h.div({ 'class' : 'uploader_progress' },
            h.div({ 'class' : 'uploader_loaded' })
          ),
          h.p({ 'class' : 'upload_basic' }, 'Uploading not working for you? ', h.a({ href: '?basic=true' }, 'try the basic uploader.'))
        )
      }));
    },
    _handleError: function(f, c, m) { 
      if (m) alert(m);
    },
    _clearDialog: function() { 
      $('#file' + this.uuid).attr('value', ''); 
      this.swfupload.cancelUpload();
    },
    _fileSelected: function(file) {
      this.fileSelected = true;
      $('#file' + this.uuid).attr('value', file.name);
    },
    _uploadProgress: function(file, loaded, total) {
      this.element.find('.uploader_loaded').css({
        width: ((loaded / total) * 100) + '%'
      });
    },
    _uploadFailed: function(file, loaded, total) {
      var submit = $(this.form).find('input[type=submit]');
      $(submit).attr('value', 'Twaudio it!');
      $(this.form).find('input[type=submit]').attr('disabled', '');
    }
  });
  
  Uploader.uuid = 0;
  
  var Recorder = $.klass({
    initialize: function(endPoint, streamName) {
      this.endPoint = endPoint;
      this.streamName = streamName;
      this._embedRecorder();
      
      this.form = this.element.parents('form');
      
      this.form.submit($.bind(this.onsubmit, this));
    },
    onsubmit: function() {
      if ($('#sound_path').val().length == 0) {
        this.form.find('input[type=submit]').val('Uploading...').attr('disabled', 'disabled');
        
        $.post('/post_recording', { 
          key: this.streamName, 
          authenticity_token: this.form.find('input[name=authenticity_token]').val()
        }, $.bind(this._gotResponse, this));
      
        return false;
      }
    },
    _gotResponse: function(response) {
      if (response == '') setTimeout($.bind(this.onsubmit, this), 1000);
      else {
        if (response == 'error') {
          alert('There was an error processing your recording.  Please try again.');
          this.form.find('input[type=submit]').val('Twaudio it!').attr('disabled', null);
        } else {
          $('#sound_path').attr('value', response);
          this.form.submit();
        }
      }
    },
    _embedRecorder: function() {
      this.element.html('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ' +  
                        'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" ' + 
                        'width="370" height="150" align="middle">' +
    	                  '<param name="allowScriptAccess" value="sameDomain" />' +
                      	'<param name="allowFullScreen" value="false" />' +
    	                  '<param name="movie" value="/swf/recorder.swf' + this._queryString() + '" /><param name="quality" value="high" />' + 
    	                  '<param name="bgcolor" value="#e6e6e6" />' +	
    	                  '<embed src="/swf/recorder.swf' + this._queryString() + '" quality="high" bgcolor="#e6e6e6" width="370" ' +
    	                  'height="150" align="middle" allowScriptAccess="sameDomain" ' + 
    	                  'allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />' +
    	                  '</object>');
    },
    _queryString: function() {
      return "?url=" + this.endPoint + "&stream_name=" + this.streamName;
    }
  });
  
  var CharacterLimiter = $.klass({
    initialize: function(readout, maxChars) {
      this.readout = $(readout);
      this.maxChars = maxChars;
    },
    onkeypress: function(e) {
      var left = this.maxChars - this.element.val().length;
      this.readout.html(left);
      
      if (left <= 0) {
        this.element.val(this.element.val().substring(0, this.maxChars - 1)); 
      }
    }
  });
  
  var ConfirmationRequired = $.klass({
    initialize: function(message) {
      this.message = message;
    },
    onsubmit: function() {
      return confirm(this.message);
    }
  })
  
  var Lightbox = $.klass({
    initialize: function(options) {
      this.options = options || {};
      this._buildMarkup();
    },
    show: function(href) {
      this.$lightbox.show();
      
      this.$bg.css({
        width: $(window).width() + 'px',
        height: $(window).height() + 'px'
      }).fadeIn('fast');
      
      $.get(href, $.bind(function(html) {
        
        this.$pane.html(html);
        
        this.$pane.css({
          top: Math.floor((this.$bg.outerHeight()/2) - (this.$pane.outerHeight()/2)) + 'px',
          left: Math.floor((this.$bg.outerWidth()/2) - (this.$pane.outerWidth()/2)) + 'px'
        });
      
        this.$pane.fadeIn('fast', $.bind(function() {
          if (this.options.open) this.options.open.call(this);
        }, this));
      }, this));
    },
    close: function() {
      var lb = this;
      
      if (this.options.close) this.options.close.call(this);
      
      lb.$pane.fadeOut('fast', function() {
        lb.$bg.fadeOut('fast', function() {
          lb.$lightbox.hide();
        });
      });
    },
    onclick: function(e) {
      this.show(this.element.attr('href'));
      return false;
    },
    _buildMarkup: function() {
      $.build(function(h) {
        h.div({ id: 'lightbox' },
          h.div({ id: 'bg' }),
          h.div({ id: 'pane' }, 'stuff')
        )
      }).appendTo(document.body);
      
      this.$lightbox = $('#lightbox').hide();
      
      this.$bg = $('#bg').hide();
      
      this.$pane = $('#pane').hide();
    }
  });
  
  return {
    AudioPlayer: AudioPlayer,
    Uploader: Uploader,
    Recorder: Recorder,
    CharacterLimiter: CharacterLimiter,
    ConfirmationRequired: ConfirmationRequired,
    Lightbox: Lightbox
  };
})();