docs: function(settings) {
      this.events = [];
      this.setSettings(settings);
      this.bytesLoaded = 0;
      this.bytesTotal = 0;
      this.paused = !this.settings.autoStart;
  
      var _self = this;
      var _fileList = [];
      var _completed = new List('item.uuid');
      var _errors = new List('item.uuid');
      var _queue = new List('item.uuid');
  
      var onStart = function(event) {
          var e = new FileManagerEvent('file_start', {
              bytesLoaded: event.bytesLoaded,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray()
          });
  
          _self.dispatchEvent(e);
      };
  
      var onPause = function(event) {
          var e = new FileManagerEvent('file_pause', {
              bytesLoaded: event.bytesLoaded,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray()
          });
  
          _self.dispatchEvent(e);
      };
  
      var onProgress = function(event) {
          _self.bytesLoaded += event.bytesLoaded;
  
          // @deprecated
          var e = new FileManagerEvent('file_progress', {
              bytesLoaded: event.bytesLoaded,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray()
          });
  
          _self.dispatchEvent(e);
  
          e = new FileManagerEvent('progress', {
              bytesLoaded: event.bytesLoaded,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray()
          });
  
          _self.dispatchEvent(e);
      };
  
      var onError = function(event) {
          _queue.remove(event.target);
          _errors.add(event.target);
  
          // @deprecated
          var e = new FileManagerEvent('file_error', {
              bytesLoaded: 0,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray(),
              fileError: event
          });
  
          _self.dispatchEvent(e);
  
          e = new FileManagerEvent('error', {
              bytesLoaded: 0,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray(),
              fileError: event
          });
  
          _self.dispatchEvent(e);
          
          queue.apply(_self);
      };
  
      var onComplete = function(event) {
          _completed.add(event.target);
          _queue.remove(event.target);
  
          // @deprecated
          var e = new FileManagerEvent('file_complete', {
              bytesLoaded: event.bytesLoaded,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray(),
              data: event.data
          });
  
          _self.dispatchEvent(e);
  
          e = new FileManagerEvent('complete', {
              bytesLoaded: event.bytesLoaded,
              bytesTotal: event.bytesTotal,
              totalBytesLoaded: _self.bytesLoaded,
              totalBytesTotal: _self.bytesTotal,
              currentTarget: event.target,
              file: event.file,
              queue: _queue.toArray(),
              errors: _errors.toArray(),
              fileList: _fileList,
              completed: _completed.toArray(),
              data: event.data
          });
  
          _self.dispatchEvent(e);
          
          queue.apply(_self);
      };
  
      _queue.add = function(item) {
          if (!!item.uuid) {
              item.on('start', onStart);
              item.on('pause', onPause);
              item.on('progress', onProgress);
              item.on('error', onError);
              item.on('complete', onComplete);
  
              this.list[item.uuid] = item;
              ++this.length;
          }
      };
      _queue.remove = function(item) {
          if (!!item.uuid) {
              item.off('start', onStart);
              item.off('pause', onPause);
              item.off('progress', onProgress);
              item.off('error', onError);
              item.off('complete', onComplete);
  
              delete this.list[item.uuid];
              --this.length;
          }
      };
  
      this.addFile = function(file) {
          if (!file instanceof File || !this.validate(file)) {
              // If it's an actual file, just throw it in the error queue
              if (file instanceof File) {
                  _errors.add(file);
                  var e = new FileManagerEvent('invalid', {
                      bytesLoaded: 0,
                      bytesTotal: file.size,
                      totalBytesLoaded: _self.bytesLoaded,
                      totalBytesTotal: _self.bytesTotal,
                      currentTarget: this,
                      queue: _queue.toArray(),
                      file: file,
                      fileList: _fileList,
                      completed: _completed.toArray(),
                      errors: _errors.toArray()
                  });
  
                  this.dispatchEvent(e);
              }
              return;
          }
  
          if (!_fileList) {
              _fileList = [];
          }
  
          _fileList.push(file);
          
          this.bytesTotal += file.size;
  
          // Update the queue
          queue.apply(this);
  
          return this;
      };
  
      this.setFiles = function(files) {
          if (!files instanceof FileList || !files instanceof Array || files.length === 0) {
              return;
          }
  
          this.pause();
          _fileList = [];
          var i;
  
          if (files instanceof FileList) {
              for (i = 0; i < files.length; i++) {
                  this.addFile(files.item(i));
              }
          }
          else {
              for (i = 0; i < files.length; i++) {
                  this.addFile(files[i]);
              }
          }
  
          if (this.settings.autoStart === true) {
              this.start();
          }
  
          return this;
      };
  
      var queue = function () {
          var _self = this;
          while(_queue.length < _self.settings.maxQueue && _fileList.length > 0) {
              var file = _fileList.shift();
              if (!!file) {
                  // Create the FileUpload to queue
                  var fu = new FileUpload(file, {
                      url: _self.settings.url,
                      method: _self.settings.method,
                      autoStart: false,
                      maxChunkSize: _self.settings.maxChunkSize,
                      formFileField: _self.settings.formFileField,
                      chunkParameter: _self.settings.chunkParameter,
                      chunksParameter: _self.settings.chunksParameter
                  });
  
                  // Update the total queue size
                  _self.bytesTotal += file.size;
  
                  // Add the uploader to the queue
                  _queue.add(fu);
  
                  // Dispatch an queue event
                  _self.dispatchEvent(new FileManagerEvent('queue', {
                      bytesLoaded: 0,
                      bytesTotal: file.size,
                      totalBytesLoaded: _self.bytesLoaded,
                      totalBytesTotal: _self.bytesTotal,
                      currentTarget: fu,
                      queue: _queue.toArray(),
                      file: file,
                      fileList: _fileList,
                      completed: _completed.toArray(),
                      errors: _errors.toArray()
                  }));
  
                  // If the manager isn't paused, start the upload
                  if (!_self.paused) {
                      fu.start();
                  }
              }
          }
      };
  
      this.start = function() {
          this.paused = false;
  
          queue.apply(this);
          
          for (var n in _queue.list) {
              _queue.get(n).start();
          }
  
          this.dispatchEvent(FileManagerEvent('start', {
              bytesLoaded: this.bytesLoaded,
              bytesTotal: this.bytesTotal,
              queue: _queue.toArray(),
              fileList: _fileList,
              completed: _completed.toArray(),
              errors: _errors.toArray()
          }));
      };
  
      this.pause = function() {
          this.paused = true;
          for (var i = 0; i < _queue.length; i++) {
              _queue[i].pause();
          }
  
          this.dispatchEvent(new FileManagerEvent('pause', {
              bytesLoaded: this.bytesLoaded,
              bytesTotal: this.bytesTotal,
              queue: _queue.toArray(),
              fileList: _fileList,
              completed: _completed.toArray(),
              errors: _errors.toArray()
          }));
      };
      
      this.clearQueue = function() {
        _queue.clear();
        return this;
      };
      
      this.clearErrors = function() {
        _errors.clear();
        return this;
      };
      
      this.clearCompleted = function() {
        _completed.clear();
        return this;
      }
  }