//
// 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
//

/* Photo Magic launches uploader when a file/photo is dropped onto a page.
 * Mediabar drag and drop is also hooked into this process.
 */

const FLOCK_RICH_CONTENT_FLAVOUR = "application/x-flock-rich-content";
const FLOCK_RICH_DND_SERVICE_CONTRACTID = "@flock.com/rich-dnd-service;1";
const FLOCK_CATEGORY_MANAGER_CONTRACTID = "@mozilla.org/categorymanager;1";
const FLOCK_SUPPORTED_SERVICE = "flockSupportedService";

var photoMagicDND = {
  canHandleMultipleItems: true,

  /* Not the conventional way of handling things, as nsDragAndDrop.dragOver
   * function breaks text reordering in textarea's.
   *
   * If we are dragging an image into a textarea enable canDrop ourselves.
   
   * This function only takes the aEvent parameter as the other parameters
   * are normally passed in by nsDragAndDrop.dragOver
   */
  onDragOver: function pmDND_onDragOver(aEvent) {
    // Since we are not calling nsDragAndDrop.dragOver we need to make sure the
    // drag service is available.
    if (!nsDragAndDrop.mDragSession) {
      nsDragAndDrop.mDragSession = nsDragAndDrop.mDragService
                                                .getCurrentSession();
      if (!nsDragAndDrop.mDragSession) {
        return;
      }
    }

    // Don't allow dropping rich content on MyWorld page
    var win = Components.classes["@mozilla.org/appshell/window-mediator;1"]
             .getService(Components.interfaces.nsIWindowMediator)
             .getMostRecentWindow("navigator:browser");
    if (win.gBrowser.currentURI.spec == "about:myworld") {
      nsDragAndDrop.mDragSession.canDrop = false;
      return;
    }

    // Get the xferData to determine if we need to enable canDrop
    var flavourSet = this.getSupportedFlavours();
    var transferData = nsTransferable.get(flavourSet,
                                          nsDragAndDrop.getDragData, true);
    // Throw away other data as we only handle one image at a time
    var xferData = transferData.first.first;

    // We should handle the drop if we are dragging rich content
    if (this._isRichContentDnD(xferData.flavour.contentType)) {
      nsDragAndDrop.mDragSession.canDrop = true;
      return;
    }

    var url = transferUtils.retrieveURLFromData(xferData.data,
                                                xferData.flavour.contentType);

    // If url isn't valid, bail out
    if (!this._isValidURL(url)) {
      return;
    }

    // This is a photo? enable canDrop
    if (FlockMedia.isAPhoto(url)) {
      nsDragAndDrop.mDragSession.canDrop = true;
    }
  },

  onDrop: function pmDND_onDrop(aEvent, aXferData, aDragSession) {
    var xferData = aXferData.first.first;

    // Handle non-rich content dropped into a non-textarea element
    if ((aEvent.target.localName.toLowerCase() != "textarea") &&
        !this._isRichContentDnD(xferData.flavour.contentType))
    {
      // XXX: TODO
      // This needs to be put into it's own overlay and own js file for proper
      // design and processing.

      contentAreaDNDObserver.onDrop(aEvent, xferData, aDragSession);
      return;
    }

    this.target = aEvent.target;

    // bail if they're dropping a selection of images (we just handle one)
    if (aXferData.dataList.length > 1) {
      var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"].getService(Components.interfaces.nsILocaleService);
      var stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
      var stringBundle = stringBundleService.createBundle("chrome://flock/locale/photo/photo.properties", localeService.getApplicationLocale());

      alert(stringBundle.GetStringFromName("flock.photo.magic.drag"));
      return;
    }

    // Handle the drop if we are dragging rich content
    if (this._isRichContentDnD(xferData.flavour.contentType)) {
      var richSvc = Components.classes[FLOCK_RICH_DND_SERVICE_CONTRACTID]
                    .getService(Components.interfaces.flockIRichDNDService);
      if (richSvc.handleDrop(aDragSession, this.target)) {
        return;
      }
    }

    // If there is no account, offer to configure one now
    if (!FlockMedia.getUploadSvc().hasOnePhotoAccount()) {
      FlockMedia.getUploadSvc().promptForAccount();
      return;
    }

    var url = transferUtils.retrieveURLFromData(xferData.data, xferData.flavour.contentType);

    // If url isn't valid, bail out
    if (!this._isValidURL(url)) {
      return;
    }

    getBrowser().dragDropSecurityCheck(aEvent, aDragSession, url);

    if (FlockMedia.isAPhoto(url)) {
      var inst = this;
      var photoUploadObserver = {
        onMediaImportStart: function( aFilename, aCount) {
        },
        onMediaImportFinish: function( aUpload, aCount ) {
          UploadUIUtils.launchSinglePhotoUpload(aUpload, inst.target);
          inst.target = null;
        },
        onMediaImportError: function(aFilename) {
          alert('The photo "' + aFilename + '" could not be uploaded because it is invalid.');
        }
      }
      Components.classes["@flock.com/metrics-service;1"]
                .getService(Components.interfaces.flockIMetricsService)
                .report("Uploader-Open", "FlockMagicDnD");
      FlockMedia.getUploadSvc().importSingleMediaItem(photoUploadObserver, url);
      aEvent.stopPropagation();
    } else {
#ifndef XP_MACOSX
#ifdef XP_UNIX
      var textarea = aEvent.target.QueryInterface(Components.interfaces.nsIDOMNSEditableElement);
      textarea.editor.insertFromDrop(aEvent);
#else
      contentAreaDNDObserver.onDrop(aEvent, xferData, aDragSession);
#endif
#else
      contentAreaDNDObserver.onDrop(aEvent, xferData, aDragSession);
#endif
    }
  },

  getSupportedFlavours: function pmDND_getSupportedFlavours() {
    var flavourSet = contentAreaDNDObserver.getSupportedFlavours();
    flavourSet.appendFlavour(FLOCK_RICH_CONTENT_FLAVOUR);
    return flavourSet;
  },

  /*** Private methods ***/

  /* Valid urls don't contain spaces ' '; if we have a space it
   * isn't a valid url, or if it's a javascript: or data: url.
   */
  _isValidURL: function pmDND__isValidURL(aURL) {
    if (!aURL || !aURL.length || aURL.indexOf(" ", 0) != -1 ||
        /^\s*(javascript|data):/.test(aURL))
    {
      return false;
    }
    return true;
  },

  /* Check if we're dragging and dropping rich content */
  _isRichContentDnD: function pmDND__isRichContentDnD(aContentType) {
    return aContentType && aContentType == FLOCK_RICH_CONTENT_FLAVOUR;
  }
};
