/**
 * PSLocal PSLocal.js file.
 * This plugin is a Gears based local persistent storage backend.
 */
(function() {
var PSLocal = window.PSLocal = function PSLocal(editor) {
  this.editor = editor;

  this.config = {
    capabilities: {
      directory_operations: true,
      file_operations: true,
      image_operations: false,
      upload_operations: true,
      import_operations: false,
      user_publish: false,
      shared_publish: false,
      user_storage: true
    },
    displayName: 'Local'
  }
}

PSLocal._pluginInfo = {
    name          : "PSLocal",
    version       : "2.0",
    developer     : "Douglas Mayle",
    developer_url : "http://xinha.org",
    license       : "BSD"
};

PSLocal.prototype.onGenerateOnce = function () {
  // We use _prepareBackend to asynchronously load the Gears backend.
  this._prepareBackend();
};

PSLocal.prototype._showGearsButton = function() {
  var self = this;
  var editor = this.editor;

  editor.config.registerButton({
      id       : 'localstorage',
      tooltip  : Xinha._lc( 'Learn About Local Storage', 'PSLocal' ),
      image    : [_editor_url + editor.config.imgURL + 'ed_buttons_main.png',2,8],
      textMode : true,
      action   : function() { self.learnDialog(); }
    }
  );
  editor.config.addToolbarElement('localstorage', 'fullscreen', 1);

  // Since this is after the editor load, we have to trigger an udate manually...
  editor._rebuildToolbar();
}

PSLocal.prototype._prepareBackend = function() {
  var self = this;
  var editor = this.editor;

  if (!this.gears_init) {
    this.gears_init = true;
    Xinha._loadback(Xinha.getPluginDir("PSLocal") + "/gears_init.js",
                   function() { 
                     self._prepareBackend();
                   });
    return;
  }

  if (!window.google || !google.gears) {
    // No gears, so no need to register.  We'll register a button, however, to
    // enable users to learn about the support we offer.
    this._showGearsButton();
    return;
  }

  if (!google.gears.factory.hasPermission) {
    if (!google.gears.factory.getPermission('Xinha', editor.imgURL('/images/xinha-small-icon.gif'), Xinha._lc( 'Enable Gears in order to use local document storage and configuration.', 'PSLocal' ))) {
      // The user has denied access to Gears.  We'll give them a UI to allow
      // them to change their mind.
      this._showGearsButton();
      return;
    }
  }

  this.workerPool = google.gears.factory.create('beta.workerpool', '1.0');  

  this.remoteStorageWorker = this.workerPool.createWorkerFromUrl("http://xinhadocs.org/worker.js");

  this._registerBackend();
}

PSLocal.prototype.learnDialog = function(timeWaited) {
  var self = this;
  var editor = this.editor;

  if (!this.html) {
    Xinha._getback(Xinha.getPluginDir("PSLocal") + "/dialog.html",
                   function(getback) { 
                     self.html = getback;
                     self.learnDialog();
                   });
    return;
  }

  if (this.dialog) {
    this.dialog.show();
    return;
  }

  this.dialog = new Xinha.Dialog(editor, this.html, "PersistentStorage", 
                                 {width: 700,
                                  closeOnEscape: true,
                                  resizable: true,
                                  centered: true,
                                  modal: true
                                 });

  var link = this.dialog.getElementById('GearsLink');

  // Tack on our URL so that Google will return here after installation.
  link.href += location.href;

  var button = this.dialog.getElementById("confirm");
  if (window.google && google.gears) {
    Xinha._addClass(this.dialog.getElementById('InstallText'), 'hidden');
    // The user has gears installed, but has denied us access to it, so we'll
    // give them the option to change their mind.
    button.value = Xinha._lc('Enable', 'PSLocal');

    button.onclick = function() {
      // The user gave us permission, so we'll reload the page.
      if (confirm(Xinha._lc('This will reload the page, causing you to lose any unsaved work.  Press "OK" to reload.', 'PSLocal' ))) {
        window.location.reload(true);
      }
    }
  } else {
    Xinha._addClass(this.dialog.getElementById('EnableText'), 'hidden');
    // Gears isn't installed, so we'll build the dialog to prompt installation.
    button.value = Xinha._lc('Install', 'PSLocal');

    button.onclick = function() {
      location.href = link.href;
    }
  }

  var cancel = this.dialog.getElementById('cancel');
  cancel.onclick = function() {
    self.dialog.hide();
  }

  this.dialog.show();
}

PSLocal.prototype._registerBackend = function(timeWaited) {
  var editor = this.editor;
  var self = this;

  if (!timeWaited) {
    timeWaited = 0;
  }

  // Retry over a period of ten seconds to register.  We back off exponentially
  // to limit resouce usage in the case of misconfiguration.
  var registerTimeout = 10000;

  if (timeWaited > registerTimeout) {
    // This is most likely a configuration error.  We're loaded and
    // PersistentStorage is not.
    return;
  }

  if (!editor.plugins['PersistentStorage'] ||
      !editor.plugins['PersistentStorage'].instance ||
      !editor.plugins['PersistentStorage'].instance.ready) {

    window.setTimeout(function() {self._registerBackend(timeWaited ? timeWaited*2 : 50);}, timeWaited ? timeWaited : 50);
    return;
  }
  var PS = editor.plugins['PersistentStorage'].instance;
  var self = this;
  
  this.config.thumbURL = this.editor.imgURL('images/tango/32x32/places/folder.png');
  this.loadDocument({URL:'', name:'config.js', key:'/config.js'}, function(json) {
                   var userconfig = json ? eval('(' + json + ')') : false;
                   PS.registerBackend('PSLocal', self, self.config, userconfig);
                   });
}

PSLocal.prototype.loadDocument = function(entry, asyncCallback) {

  this.workerPool.onmessage = function(a, b, message) {
    if (!message.body || !message.body.authorized) {
      // Fail
      asyncCallback('');
    }

    if (message.body.response) {
      asyncCallback(message.body.response);
    } else if (entry.URL) {
      Xinha._getback(entry.URL,
                 function(documentSource) { 
                   asyncCallback(documentSource);
                 });
    } else {
      // Oops, no data :-(
      asyncCallback('');
    }
  }

  this.workerPool.sendMessage({func: 'loadDocument', entry: entry}, this.remoteStorageWorker);
}

PSLocal.prototype.loadData = function (asyncCallback) {
  this.workerPool.onmessage = function(a, b, message) {
    if (!message.body || !message.body.authorized) {
      // Fail
      asyncCallback('');
    }

    asyncCallback({dirs: message.body.dirs, files: message.body.files});
  }

  this.workerPool.sendMessage({func: 'loadData'}, this.remoteStorageWorker);
}

PSLocal.prototype.getFilters = function(filedata) {
  // Clear out the previous directory listing.
  var filters = [], paths = {};
  var dirList = filedata.dirs;

  for (var index=0; index<dirList.length; ++index) {
    filters.push({value:dirList[index],display:dirList[index]});
  }

  // We can't return an empty filter list.
  if (!filters.length) {
    filters.push({value:'/',display:'/'});
  }

  return filters;
}

PSLocal.prototype.getMetadata = function(filedata, filterPath) {
  var editor = this.editor;
  var self = this;

  var metadata = [];
  var fileList = filedata.files;

  for (var index=0; index<fileList.length; ++index) {
      // Gah perform file splitting here..
    var pathpart = fileList[index].fullpath.split('/');
    if (pathpart.length > 2) {
      pathpart = pathpart.slice(0,pathpart.length-1).join('/');
    } else {
      pathpart = '/';
    }

    var filepart = fileList[index].fullpath.split('/').slice(-1)[0];
    if (filterPath == pathpart) {
      metadata.push({
        URL: fileList[index].url,
        thumbURL: editor.imgURL('images/tango/32x32/mimetypes/text-x-generic.png'),
        name: filepart,
        key: fileList[index].fullpath,
        $type: fileList[index].filetype
      });
    }
  }

  var dirList = filedata.dirs;

  for (var index=0; index<dirList.length; ++index) {
    // We have to be careful to filter out when filterPath IS the current intry in dirList
    if (1 == filterPath.length) {
        // If the filter path is the root '/' (ie. length of one) then we
        // select the directory if a) It is not also of length one (ie. '/')
        // and b) has only one slash in it.  (We check the number of slashes by
        // splitting the string by '/' and subtracting one from the length.)
        var matches = dirList[index].length > 1 && dirList[index].split('/').length == 2;
    } else {
        // Chop the last component of the directory and compare against the filter.
        var matches = dirList[index].split('/').slice(0,-1).join('/') == filterPath;
    }
    if (matches) {
      metadata.push({
        name: dirList[index].split('/').slice(-1),
        key: dirList[index],
        $type: 'folder'
      });
    }
  }

  return metadata;
}

PSLocal.prototype.saveDocument = function(parentpath, filename, documentSource, asyncCallback) {
  this.workerPool.onmessage = function(a, b, message) {
    if (!message.body || !message.body.authorized) {
      // Fail
      asyncCallback(false);
    }

    if (asyncCallback) {
      asyncCallback(message.body.response);
    }
  }

  this.workerPool.sendMessage({func: 'saveDocument', parentpath: parentpath, filename: filename, content:documentSource}, this.remoteStorageWorker);
}
PSLocal.prototype.deleteEntry = function(entry, asyncCallback) {
  this.workerPool.onmessage = function(a, b, message) {
    if (!message.body || !message.body.authorized) {
      // Fail
      asyncCallback(false);
    }

    if (asyncCallback) {
      asyncCallback(message.body.response);
    }
  }

  this.workerPool.sendMessage({func: 'deleteEntry', entry: entry}, this.remoteStorageWorker);
}

PSLocal.prototype.makeFolder = function(currentPath, folderName, asyncCallback) {
  this.workerPool.onmessage = function(a, b, message) {
    if (!message.body || !message.body.authorized) {
      // Fail
      asyncCallback(false);
    }

    if (asyncCallback) {
      asyncCallback(true);
    }
  }

  this.workerPool.sendMessage({func: 'makeFolder', parentpath: currentPath, dirname: folderName}, this.remoteStorageWorker);
}

PSLocal.prototype.copyEntry = function(entry, asyncCallback) {
  this.workerPool.onmessage = function(a, b, message) {
    if (!message.body || !message.body.authorized) {
      // Fail
      asyncCallback(false);
    }

    if (asyncCallback) {
      asyncCallback(message.body.response, message.body.entry);
    }
  }

  this.workerPool.sendMessage({func: 'copyEntry', entry: entry}, this.remoteStorageWorker);
}

})();
