// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2008
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL

const CC = Components.classes;
const CI = Components.interfaces;
const CU = Components.utils;

CU.import("resource:///modules/FlockStringBundleHelpers.jsm");
CU.import("resource:///modules/FlockXPCOMUtils.jsm");

const FLOCK_SHELF_CLASS_NAME = "Flock Shelf Service";
const FLOCK_SHELF_CLASS_ID =
  Components.ID("{ee266aa8-bc64-4e6a-9a20-1143b0444fbd}");
const FLOCK_SHELF_CONTRACTID =
  "@mozilla.org/rdf/datasource;1?name=flock-shelf";

const FLOCK_NS = "http://flock.com/rdf#";
const FLOCK_SHELF_ROOT = "urn:flock:shelfroot";

const OLD_SHELF_RDF_FILE = "flock_shelf.rdf";
const OLD_SHELF_RDF_FILE_RELIC = "flock_shelf_old.rdf";

function flockShelfService() {
  this._coop = CC["@flock.com/singleton;1"]
               .getService(CI.flockISingleton)
               .getSingleton("chrome://flock/content/common/load-faves-coop.js")
               .wrappedJSObject;

  this._logger = CC['@flock.com/logger;1'].createInstance(CI.flockILogger);
  this._logger.init("shelfservice");

  this.shelfRoot = this._coop.get(FLOCK_SHELF_ROOT);
  if (!this.shelfRoot) {
    this.shelfRoot = new this._coop.Folder(FLOCK_SHELF_ROOT);
    this._coop.favorites_root.children.add(this.shelfRoot);
  }
}

flockShelfService.prototype = new FlockXPCOMUtils.genericComponent(
  FLOCK_SHELF_CLASS_NAME,
  FLOCK_SHELF_CLASS_ID,
  FLOCK_SHELF_CONTRACTID,
  flockShelfService,
  CI.nsIClassInfo.SINGLETON,
  [
    CI.flockIShelfService,
    CI.flockIMigratable
  ]
);

flockShelfService.prototype._xpcom_categories = [
  { category: "flockMigratable" }
];


//flockIMigratable

flockShelfService.prototype.__defineGetter__("migrationName",
function getter_migrationName() {
  return flockGetString("common/migrationNames", "migration.name.shelf");
});

flockShelfService.prototype.needsMigration =
function needsMigration(oldVersion) {
  this._logger.debug(".needsMigration('" + oldVersion + "')");

  if (oldVersion.substr(0, 3) == "0.7") { // migration from Cardinal (0.7.x)
    var oldShelfFile = CC["@mozilla.org/file/directory_service;1"]
                       .getService(CI.nsIProperties)
                       .get("ProfD", CI.nsIFile);
    oldShelfFile.append(OLD_SHELF_RDF_FILE);

    if (oldShelfFile.exists()) {
      this._logger.info("needs migration from 0.7.x");
      return true;
    }
    return false;
  } else {
    return false;
  }
}

flockShelfService.prototype.startMigration =
function startMigration(oldVersion, aFlockMigrationProgressListener) {
  this._logger.debug(".startMigration('"
                     + oldVersion
                     + "', 'aFlockMigrationProgressListener')");
  var ctxt = {
    oldVersion: oldVersion,
    listener: aFlockMigrationProgressListener
  };

  if (oldVersion.substr(0, 3) == "0.7") { // migration from Cardinal (0.7.x)
    var oldShelfFile = CC["@mozilla.org/file/directory_service;1"]
                       .getService(CI.nsIProperties)
                       .get("ProfD", CI.nsIFile);
    oldShelfFile.append(OLD_SHELF_RDF_FILE);

    ctxt.oldShelfFile = oldShelfFile;

    if (oldShelfFile.exists()) {
      ctxt.listener.onUpdate(0, "Migrating web clipboard");
    }
  }

  return { wrappedJSObject: ctxt };
}

flockShelfService.prototype.finishMigration =
function finishMigration(ctxtWrapper) {
}

flockShelfService.prototype.doMigrationWork =
function doMigrationWork(ctxtWrapper) {
  var ctxt = ctxtWrapper.wrappedJSObject;
  var oldVersion = ctxt.oldVersion.substr(0, 3);

  if (oldVersion == "0.7") {
    if (!ctxt.oldShelfFile.exists()) {
      return false;
    }

    var rdfs = CC["@mozilla.org/rdf/rdf-service;1"]
              .getService (CI.nsIRDFService);
    var ios = CC['@mozilla.org/network/io-service;1']
              .getService (CI.nsIIOService);

    var shelfDS = rdfs.GetDataSourceBlocking(ios.newFileURI(ctxt.oldShelfFile).spec);
    var shelfRes = rdfs.GetResource("urn:flock:shelf:objects");
    var container = CC["@mozilla.org/rdf/container;1"].createInstance(CI.nsIRDFContainer);
    container.Init(shelfDS, shelfRes);

    var importFolderId;
    var children = container.GetElements();
    while (children.hasMoreElements()){
      var child = children.getNext().QueryInterface(CI.nsIRDFResource);

      var nameRes = rdfs.GetResource("http://www.flock.com/rdf/shelf#title");
      var name = shelfDS.GetTarget(child, nameRes, true)
                        .QueryInterface(CI.nsIRDFLiteral);
      var contentRes = rdfs.GetResource("http://www.flock.com/rdf/shelf#content");
      var content = shelfDS.GetTarget(child, contentRes, true)
                           .QueryInterface(CI.nsIRDFLiteral);
      var urlRes = rdfs.GetResource("http://www.flock.com/rdf/shelf#url");
      var url = shelfDS.GetTarget(child, urlRes, true)
                       .QueryInterface(CI.nsIRDFLiteral);
      var typeRes = rdfs.GetResource("http://www.flock.com/rdf/shelf#type");
      var type = shelfDS.GetTarget(child, typeRes, true)
                        .QueryInterface(CI.nsIRDFLiteral);
      var source = "";
      var sourceRes = rdfs.GetResource("http://www.flock.com/rdf/shelf#source");
      var sourceTarget = shelfDS.GetTarget(child, sourceRes, true);
      if (sourceTarget instanceof CI.nsIRDFLiteral) {
        sourceTarget.QueryInterface(CI.nsIRDFLiteral);
        source = sourceTarget.Value;
      }

      var myType;
      if (type.Value == "note") {
        // The "note" type is deprecated
        myType = "document";
      } else {
        myType = type.Value;
      }

      ctxt.listener.onUpdate(0, 'Importing clipping: ' + name.Value);
      this.insert(name.Value, source, url.Value, myType, -1, null);
    }

    // archive the shelf rdf file
    ctxt.oldShelfFile.moveTo(null, OLD_SHELF_RDF_FILE_RELIC);
  }

  return false;
}

// Shelf Interface Implementation
flockShelfService.prototype.elementsCount =
function SHELF_elementsCount() {
  return this._getChildCount(this.shelfRoot);
}

flockShelfService.prototype.insert =
function SHELF_insert(aTitle, aContent, aUrl, aType, aPos, aParent) {
  var date = new Date();
  var id = FLOCK_SHELF_ROOT
           + ":obj_" + date.getTime()
           + ":" + Math.round(100 * Math.random());

  var item = new this._coop.WebSnippet(id,
    {
      content: aContent, 
      name: aTitle, 
      creationDate: date, 
      URL: aUrl, 
      snippetType: aType
    });

  var parentNode = aParent ? this._coop.get(aParent) : this.shelfRoot;
  if (aPos < 0) {
    parentNode.children.add(item);
  } else {
    parentNode.children.insertAt(item, aPos);
  }

  this._refreshCount(parentNode);
  return id;
}


flockShelfService.prototype.createFolder =
function SHELF_createFolder(aName) {
  var id = FLOCK_SHELF_ROOT + ":folder:" + aName;

  var folder = new this._coop.Folder(id, { name: aName });
  this.shelfRoot.children.add(folder);

  return id;
}

flockShelfService.prototype.moveTo =
function SHELF_moveTo(aId, aFolder) {
  var folderId = FLOCK_SHELF_ROOT + ":folder:" + aFolder;

  var item = this._coop.get(aId);
  if (!item) {
    debug("*** ERROR: Can't find "+aId+"\n");
    return;
  }

  var folder = this._coop.get(folderId); 
  if (!folder) {
    this.createFolder(aFolder);
    folder = this._coop.get(folderId); 
  }

  if (folder.children.indexOf(item) > 0) {
    // Already in the folder
    return;
  }

  var parent = item.getParent();
  parent.children.remove(item);
  folder.children.add(item);

  this._refreshCount(parent);
  this._refreshCount(folder);
}

flockShelfService.prototype.changeAttribute =
function SHELF_changeAttribute(aUrn, aAttribute, aValue){
  var snippet = this._coop.get(aUrn);
  snippet[aAttribute] = aValue;
}

flockShelfService.prototype.getPositionOf =
function SHELF_getPositionOf(aUrn) {
  var snippet = this._coop.get(aUrn);

  var parent = snippet.getParent();
  return parent.children.indexOf(snippet);
}

flockShelfService.prototype.getTargetOf =
function SHELF_getTargetOf(aUrn, aTarget) {
  var snippet = this._coop.get(aUrn);
  return (snippet ? snippet[aTarget] : null);
}

flockShelfService.prototype.remove =
function SHELF_remove(aUrn) {
  var snippet = this._coop.get(aUrn);

  var parent = snippet.getParent();
  parent.children.remove(snippet);
  this._refreshCount(parent);

  snippet.destroy();
}

flockShelfService.prototype.clear =
function SHELF_clear() {
  var children = this.shelfRoot.children.enumerate();
  var elts = [];
  while (children.hasMoreElements()) {
    elts.push(children.getNext());
  }
  while (elts.length > 0) {
    var elt = elts.pop();
    this.shelfRoot.children.remove(elt);
    elt.destroy();
  }
}

flockShelfService.prototype._getChildCount =
function SHELF__getChildCount(obj) {
  var count = 0;

  var children = obj.children.enumerate();
  while (children.hasMoreElements()) {
    children.getNext();
    count++;
  }

  return count;
}

flockShelfService.prototype._refreshCount =
function SHELF__refreshCount(aFolder) {
  if (!aFolder.children) {
    return;
  }

  aFolder.count = this._getChildCount(aFolder);
}

var NSGetModule = FlockXPCOMUtils.generateNSGetModule(FLOCK_SHELF_CLASS_NAME,
                                                      [flockShelfService]);
