// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2009
// 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 FOLDERICON = "chrome://global/skin/tree/folder.png";

var gShelf;
var gShelfContext;
var gCurrentItem = null;
var gMetrics = Components.classes["@flock.com/metrics-service;1"]
               .getService(Components.interfaces.flockIMetricsService);
var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);

function createNotesFolder(aFolder) {
  var thumbnail = FOLDERICON;
  var title = aFolder.name;
  var folderUrn = aFolder.id();

  var item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "media");
  item.setAttribute('type', 'person'); // Ok, this is not a person but it works anyway
  item.setAttribute('thumbnail', thumbnail);
  item.setAttribute('title', title);
  item.setAttribute('tooltiptext', title);
  item.setAttribute('url', folderUrn);
  item.setAttribute('onclick', 'goToFolder(this.url)');

  var slidey = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "slideyitem");
  slidey.appendChild(item);

  return slidey;
}


var faves = Components.classes['@mozilla.org/rdf/datasource;1?name=flock-favorites']
            .getService(Components.interfaces.nsIRDFDataSource);

var faves_coop = Components.classes["@flock.com/singleton;1"]
                           .getService(Components.interfaces.flockISingleton)
                           .getSingleton("chrome://flock/content/common/load-faves-coop.js")
                           .wrappedJSObject;

function _getSupportedFlavours() {
  var flavors = new FlavourSet();
  flavors.appendFlavour("application/x-flock-rich-content");
  flavors.appendFlavour("text/html");
  flavors.appendFlavour("text/unicode");
  flavors.appendFlavour("text/x-moz-url");
  return flavors;
}

function onLoad_shelf() {
  this.gMetrics.report("WebClipboard-Opened", null);

  window.gShelfTreeObserver = {
    canDrop: function (aDOMNode, aOrientation) {
      // The only drop we don't support is on items (on folders, or before/after is OK)
      if ((aDOMNode.tagName == "richtreeitem") && (aOrientation == "on"))
        return false;
      return true;
    },

    onDrop: function (aDOMNode, aOrientation, aDropData) {
      var dragSession = dragService.getCurrentSession();
      var data = flock_getMarkedUpSelection(dragSession);
      addObject (data, aDOMNode, aOrientation);
    },

    getSupportedFlavours: function() {
      return _getSupportedFlavours();
    }
  }

  document.getElementById("notesContainer")
          .addObserver(window.gShelfTreeObserver);

  // Add an observer to refresh the clear all button/message (empty or not)
  window.gShelfRDFObserver = {
    onAssert: function () { refreshNotesUI(); },
    onUnassert: function () { refreshNotesUI(); },
    onBeginUpdateBatch: function () { },
    onChange: function () { },
    onEndUpdateBatch: function () { },
    onMove: function () { }
  };
  faves.AddObserver(window.gShelfRDFObserver);
  refreshNotesUI();
}

function onUnload_shelf() {
  this.gMetrics.report("WebClipboard-Close", null);

  faves.RemoveObserver(window.gShelfRDFObserver);
  document.getElementById("notesContainer")
          .removeObserver(window.gShelfTreeObserver);
}

function refreshNotesUI() {
  // dump("FIXME: do the following only when the change applies to a shelf object\n");
  if (shelf_service.isEmpty()) {
    document.getElementById("clear").setAttribute("disabled", "true");
  }
  else {
    document.getElementById("clear").setAttribute("disabled", "false");
  }
}

function openSelected(aLocation) {
  var itemId = document.getElementById("notesContainer").selectedItems[0].id;

  var item = faves_coop.get(itemId);
  var params = {
    title: item.name,
    content: item.content
  }

  window.openDialog("chrome://flock/content/shelf/previewSnippet.xul",
                    "_blank",
                    "chrome,close,titlebar,resizable=yes,toolbar=no,scrollbars=yes,centerscreen",
                    params); 
}

function deleteSelected() {
  var bundle = flock_shelf.getStringBundle();
  var items = document.getElementById("notesContainer").selectedItems;

  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                    .getService(Components.interfaces.nsIPromptService);
  if (prompts.confirm(window, bundle.GetStringFromName("flock.shelf.deleteSelected.title"),
                      bundle.GetStringFromName("flock.shelf.deleteSelected"))) {
    for (i = 0; i < items.length; i++)
      SHELF_SRV.remove(items[i].id);
  }
}

function deleteOne(aId) {
  var bundle = flock_shelf.getStringBundle();
  if (!aId && !document.getElementById("notesContainer").selectedItems[0]) {
    return;
  }
  var id = aId ? aId : document.getElementById("notesContainer").selectedItems[0].id;

  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                    .getService(Components.interfaces.nsIPromptService);
  if (prompts.confirm(window, bundle.GetStringFromName("flock.shelf.deleteOne.title"),
                      bundle.GetStringFromName("flock.shelf.deleteOne")))
    SHELF_SRV.remove(id);
}

function deleteFolder(aId) {
  var bundle = flock_shelf.getStringBundle();
  if (!aId && !document.getElementById("notesContainer").selectedItems[0])
    return;
  var id = aId ? aId : document.getElementById("notesContainer").selectedItems[0].id;

  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                    .getService(Components.interfaces.nsIPromptService);
  if (prompts.confirm(window, bundle.GetStringFromName("flock.shelf.deleteFolder.title"),
                      bundle.GetStringFromName("flock.shelf.deleteFolder")))
    SHELF_SRV.remove(id);
}

function deleteAll() {
  var bundle = flock_shelf.getStringBundle();
  var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                    .getService(Components.interfaces.nsIPromptService);
  if (prompts.confirm(window, bundle.GetStringFromName("flock.shelf.menu.delete.title"),
                      bundle.GetStringFromName("flock.shelf.menu.delete")))
    SHELF_SRV.clear();
}

function refreshNotesContext() {
  var cardinal = document.getElementById("notesContainer").selectedItems.length;
  if (cardinal > 1) {
    document.getElementById("deleteOne").setAttribute("hidden", "true");
    document.getElementById("deleteSelected").setAttribute("hidden", "false");
  }
  else if (cardinal > 0) {
    document.getElementById("deleteOne").setAttribute("hidden", "false");
    document.getElementById("deleteSelected").setAttribute("hidden", "true");
  }
  else {
    document.getElementById("deleteOne").setAttribute("hidden", "false");
    document.getElementById("deleteOne").setAttribute("disabled", "true");
    document.getElementById("deleteSelected").setAttribute("hidden", "true");
  }
}

function _getSrc(aItem) {
  if (aItem.nodeName == "richtreefolder") {
    var src = " ";
    for (var i = 0; i < aItem.childNodes.length; i++)
      src += _getSrc(aItem.childNodes[i]);
    return src;
  }
  else {
    return ("<p>" + aItem.firstChild.getAttribute('src') + "</p>");
  }
}

function getSrc(aItem) {
  if (aItem.nodeName == "richtreefolder")
    return _getSrc(aItem);
  else
    return aItem.firstChild.getAttribute('src');
}

function getTextUnicode(aItem) {
  var textUnicode = "";
  if (aItem.nodeName == "richtreefolder") {
    for (var i = 0; i < aItem.childNodes.length; i++) {
      if (i > 0 && textUnicode) {
        textUnicode += "\n\n";
      }
      textUnicode += getTextUnicode(aItem.childNodes[i]);
    }
  } else {
    var title = aItem.firstChild.getAttribute("label");
    var src = aItem.firstChild.getAttribute("src");
    var type = aItem.firstChild.getAttribute("type");
    if (type == "image" || type == "link") {
      // Get the link for the item
      var url = aItem.firstChild.getAttribute("url");
      if (!url) {
        // If it's not there, parse the source for the URL of the item's page.
        const RE = /<a.+?href="(.+?)"|<embed.+?\>(.+?)<\/|<embed.+?src="(.+?)"/;
        var matches = src.match(RE) || [];

        // Iterate through the results to find the first value.
        for (var idx = 1; idx < matches.length; idx++) {
          if (matches[idx]) {
            url = matches[idx];
            break;
          }
        }
      }

      if (type == "image") {
        textUnicode = ((title.length) ? (title + ":\n") : "") + url;
      } else {
        textUnicode = ((title != url) ? (title + ":\n") : "") + url;
      }
    } else {
      // Not an image or link so use content
      var url = Components.classes["@mozilla.org/feed-unescapehtml;1"]
                          .getService(Components.interfaces
                                                .nsIScriptableUnescapeHTML)
                          .unescape(src);
      textUnicode = ((title.length) ? (title + ":\n") : "") + url;
    }
  }
  return textUnicode;
}

var notesObserver = {
  dndInProgress : false,
  onDragStart: function(event, transferData, action) {
    this.dndInProgress = true;
    var items = document.getElementById("notesContainer").selectedItems;
    var src = "";
    var textUnicode = "";
    if (items.length == 0) {
      return;
    } else if (items.length == 1) {
      src = getSrc(items[0]);
      textUnicode = getTextUnicode(items[0]);
    } else {
      for (i = 0; i < items.length; i++) {
        src += "<p>" + getSrc(items[i]) + "</p>";
        if (i > 0 && textUnicode) {
          textUnicode += "\n\n";
        }
        textUnicode += getTextUnicode(items[i]);
      }
    }
    transferData.data=new TransferData();
    transferData.data.addDataForFlavour("text/html", src);
    transferData.data.addDataForFlavour("text/unicode", textUnicode);
    transferData.data.addDataForFlavour("flock/shelficon", src);
  },

  onDragOver: function(aEvent, aFlavor, aSession) {
  },

  onDrop: function (evt, dropData, asession) {
    if (gCurrentItem) {
      try { gCurrentItem.removeAttribute('dragOver'); }
      catch(e) { dump(e); }
    }
    // Files from desktop are not supported
    // (for some reason, files appear as text/unicode)
    if ((dropData.flavour.contentType == "text/unicode") &&
        (dropData.data.substring(0, 7) == "file://")) {
      return false;
    }
    var data = flock_getMarkedUpSelection(asession);
    addObject(data, null, null);
    return true;
  },

  onDragExit: function(aEvent, aFlavor, aSession) {
    this.dndInProgress = false;
  },

  getSupportedFlavours: function() {
    return _getSupportedFlavours();
  }
}

function isAncestor(aItem1, aItem2) {
  var parents = aItem2.getParents();
  for (i in parents) {
    if ((parents[i].id() == aItem1.id()) ||
        isAncestor(aItem1, parents[i]))
      return true;
  }
  return false;
}

function addObject(aData, aDOMNode, aOrientation) {
  var data = aData;
  var title;
  var content;
  var url;
  var parentNode = faves_coop.get('urn:flock:shelfroot');
  var pos = -1;
  var type = data.type;
  var bundle = flock_shelf.getStringBundle();
  var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                      .getService(Components.interfaces.nsIPromptService);

  if (aDOMNode) {
    var aCoopNode = faves_coop.get(aDOMNode.id);
    if (aCoopNode instanceof faves_coop.Folder) {
      parentNode = aCoopNode;
      pos = -1;
    } else if (aCoopNode instanceof faves_coop.WebSnippet) {
      parentNode = aCoopNode.getParent();
      pos = parentNode.children.indexOf(aCoopNode);
      if (aOrientation == "after")
        pos++;
    }
  }

  if (data.dragfrom) {
    var items = document.getElementById("notesContainer").selectedItems;

    for (var i = 0; i < items.length; i++) {
      var item = faves_coop.get(items[i].id);

      if (item.id() == parentNode.id()) {
        // Make sure we're not dropping a folder to itself
        var title = bundle.GetStringFromName("flock.shelf.error.title");
        var message = bundle.GetStringFromName("flock.shelf.error.dragOnItself");
        promptService.alert(window, title, message);
      } else if (isAncestor(item, parentNode)) {
        // Make sure we're not dropping a folder to its child
        var title = bundle.GetStringFromName("flock.shelf.error.title");
        var message = bundle.GetStringFromName("flock.shelf.error.dragOnChild");
        promptService.alert(window, title, message);
      }
      else {
        // Remove the item from its original parent
        item.getParent().children.remove(item);
        // Add it where it should go
        if (pos < 0)
          parentNode.children.add(item);
        else
          parentNode.children.insertAt(item, pos++);
      }
    }
  }
  else {
    SHELF_SRV.insert(data.title, data.content, data.URL, data.type, pos, parentNode.id());
  }

  gMetrics.report("WebClipboard-Drop", data.type);

  // we also want to clear the selection
  // this.clearSelection();
}

function newFolder(event) {
  var bundle = flock_shelf.getStringBundle();
  var check = {value: false};
  var input = {value: ""};
  var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  var result = promptService.prompt(null,
    bundle.GetStringFromName("flock.shelf.newFolder.title"),
    bundle.GetStringFromName("flock.shelf.newFolder"),
    input, null, check)
  if (result) {
    SHELF_SRV.createFolder(input.value);
  }
}

/* DS: As we mouseover the surrounding elements we don't want to show the
   tooltip during an in progress Drag and Drop is in progress
*/
function shelfShowTooltip() {
  return !notesObserver.dndInProgress;
}
