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

Components.utils.import("resource:///modules/FlockCryptoHash.jsm");

function PhotoDropProcessor(aList, aHoverChild)  {
  this.mList = aList;
  this.mHoverChild = aHoverChild;
  this.mUploaderSvc = FlockMedia.getUploadSvc();
}

PhotoDropProcessor.prototype = {
  mList: null,
  start: function() {
    var str = "";
    if (this.mHoverChild) {
      var newThing = Components.classes['@flock.com/photo-upload;1']
                               .createInstance(Components.interfaces.flockIPhotoUpload);
      newThing.id = this.mHoverChild.getAttribute("id");
      this.mHoverChild = newThing;
    }
    this.mUploaderSvc.addObserver(this);
    this.next();
  },
  next: function() {
    if (this.mList.length == 0) {
      this.mUploaderSvc.startImportQueue();
      return;
    }
    var url = this.mList.shift();
    if (url.split(":")[0] == "file") {
      this.mUploaderSvc.addMediaToImportQueue(url);
      this.next();
    } else {
      // dnding from a remote source
      var URIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
                               .getService(Components.interfaces.nsIURIFixup);
      var uri = URIFixup.createFixupURI(url, URIFixup.FIXUP_FLAG_NONE);
      
      var IOService = Components.classes["@mozilla.org/network/io-service;1"]
                                .getService(Components.interfaces.nsIIOService);
      var channel = IOService.newChannelFromURI(uri);
      
      var self = this;
      
      var streamListener = {
        processor: self,
        sinkFile: null,
        sinkBufferStream: null,
        
        onStartRequest: function(request, context) {
          var extension;
          switch (channel.contentType) {
            case "image/jpeg": extension = "jpg"; break;
            case "image/png": extension = "png"; break;
            case "image/gif": extension = "gif"; break;
            default: extension = "jpg"; break;
          }
          //var sinkFileName = "remoteImage." + extension;
          var sinkFileName = url.split("/").pop().replace(/[\?=&]/g, '');
          this.sinkFile = Components.classes["@mozilla.org/file/directory_service;1"]
                                    .getService(Components.interfaces.nsIProperties)
                                    .get("ProfD", Components.interfaces.nsIFile);
          this.sinkFile.append("flock_imagecache");
          if (!this.sinkFile.exists()) {
            this.sinkFile.createUnique(this.sinkFile.DIRECTORY_TYPE, 0700);
          }
          if (sinkFileName) this.sinkFile.append(sinkFileName);

          var sinkFileStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                                         .createInstance(Components.interfaces.nsIFileOutputStream);
          sinkFileStream.init(this.sinkFile, 0x02 | 0x08 | 0x20, 0664, 0);
          this.sinkBufferStream = Components.classes["@mozilla.org/network/buffered-output-stream;1"]
                                            .createInstance(Components.interfaces.nsIBufferedOutputStream);
          this.sinkBufferStream.init(sinkFileStream, 65536 * 4);
        },
        
        onStopRequest: function(request, context, statusCode) {
          var ios = Components.classes["@mozilla.org/network/io-service;1"]
                              .getService(Components.interfaces.nsIIOService);
          var fileHandler = ios.getProtocolHandler("file")
                               .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
          this.sinkBufferStream.close();
          var url = fileHandler.getURLSpecFromFile(this.sinkFile);
          this.processor.mUploaderSvc.addMediaToImportQueue(url);
          this.processor.next();
        },
        
        onDataAvailable: function(request, context, inputStream, offset, count) {
          this.sinkBufferStream.writeFrom(inputStream, count);
        }
      }

      channel.asyncOpen(streamListener, null);
    }
  },
  onMediaBatchImportStart: function(aNumImport) {
  },
  onMediaBatchImportFinish: function() {
    this.mUploaderSvc.removeObserver(this);
  },
  onMediaImportStart: function(aFilename, aNum) {
  },
  onMediaImportFinish: function(aPhotoUpload) {
    this.mUploaderSvc.addPhotoUpload((this.mHoverChild?this.mHoverChild:null),aPhotoUpload);
  },
  onMediaImportError: function(aFile) {
    var stringBundle = FlockMedia.getStringBundle();
    alert(stringBundle.GetStringFromName("flock.photo.upload.error.invalid").replace("%1",aFile));
    this.next();
  },
  onUploadAdd: function() {
  },
  onUploadRemove: function() {
  },
  onError: function(aError) {
    alert(aError.errorString);
    this.next();
  },
  cancel: function() {
    // not impl
  }
}

var photoUploadDNDObserver = {
  canDrop: function (aEvent, aDragSession) {
    var isPhoto = true;
    var node = aDragSession.sourceNode;
    if (node) {
      var nodeName = node.nodeName.toLowerCase();
      if (nodeName == "photo") {
        // We currently don't support uploading mediabar videos or
        // drag-and-drop from the mediabar to itself
        isPhoto = (!this._isRichVideo(aDragSession)) &&
                  (aEvent.target.nodeName.toLowerCase() != "photo");
      } else {
        isPhoto = (nodeName == "img") ||
                  (nodeName == "shelficon") ||
                  (nodeName == "photoupload");
      }
    }
    return (isPhoto && 
            !FlockMedia.getUploadSvc().isImporting &&
            !FlockMedia.getUploadSvc().isUploading);
  },

  canHandleMultipleItems: true,

  onDragOver: function(aEvent, aFlavor, aSession) {
    if (!this._isRichVideo(aSession)) {
      aEvent.target.setAttribute("dropzoneengaged", "true");
    }
  },

  onDragEnter: function(aEvent, aSession) {
    if (!this._isRichVideo(aSession)) {
      var target = aEvent.target;
      if (this._isHoverOverUploadButton(target)) {
        target = target.parentNode;
      }
      target.setAttribute("dropzoneengaged", "true");
    }
  },

  onDragExit: function(aEvent, aSession) {
    if (!this._isRichVideo(aSession)) {
      var target = aEvent.target;
      if (this._isHoverOverUploadButton(target)) {
        target = target.parentNode;
      }
      target.removeAttribute("dropzoneengaged");
    } 
  },

  onDrop: function(aEvent, aDropData, aSession) {
    FlockMedia.getLogger().debug( "photoUploadDNDObserver: drop: sourceNode: "
           + (aSession.sourceNode ? aSession.sourceNode.localName : "none")
           + " items: "+aDropData.dataList.length );
    aEvent.stopPropagation();
    var photoURLs = new Array();

    for (var c = 0; c < aDropData.dataList.length; c++) {
      var supports = aDropData.dataList[c].dataList[0].supports;
      var contentType = aDropData.dataList[c].dataList[0].flavour.contentType;
      var url;

      if (aSession.sourceNode && aSession.sourceNode.localName == "IMG") {
        contentType = null;
      }

      switch (contentType) {
        case "application/x-moz-file":
          try {
            var file = supports.QueryInterface(Components.interfaces.nsIFile);
            handleFile(file, photoURLs);
          } catch(e) {}
          break;
        case "application/flock-photo":
          url = aSession.sourceNode.largeSizePhoto;
          photoURLs.push(url);
          break;
        case "flock/shelficon":
          url = aSession.sourceNode.url;
          photoURLs.push(url);
          break;
        default:
          if (aSession.sourceNode && aSession.sourceNode.localName == "IMG") {
            url = aSession.sourceNode.getAttribute("src");
            var baseURI = aSession.sourceDocument.baseURI;
            var URIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
                                     .getService(Components.interfaces.nsIURIFixup);
            url = URIFixup.createFixupURI(baseURI, URIFixup.FIXUP_FLAG_NONE).resolve(url);
            photoURLs.push(url);
          } else {
            url = supports.QueryInterface(Components.interfaces.nsISupportsString).data;
            url = url.split("\n")[0];
            if (FlockMedia.isAPhoto(url)) {
              photoURLs.push(url);
            } else {
              if (url.indexOf("file") == 0) {
                var ios = Components.classes["@mozilla.org/network/io-service;1"]
                                    .getService(Components.interfaces.nsIIOService);
                var fileHandler = ios.getProtocolHandler("file")
                                     .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
                var sourceSpec = fileHandler.getFileFromURLSpec(url);
                if (sourceSpec.exists()) {
                  handleFile(sourceSpec, photoURLs);
                }
              }
            }
          }
          break;
      }
    }

    FlockMedia.getLogger().debug("photoUploadDNDObserver: found "
                                 + photoURLs.length
                                 + " image(s)");

    var hoverNode = null;
    if (aEvent.target.nodeName == "slideyitem") {
      hoverNode = aEvent.target.parentNode.hoverChild.firstChild;
    }
    if (aEvent.target.nodeName == "photoupload") {
      var slideyboxHover = aEvent.target.parentNode.parentNode.hoverChild;
      if (slideyboxHover) {
        hoverNode = slideyboxHover.firstChild;
      }
    }
    
    if (photoURLs.length) {
      FlockMedia.getUploadSvc().launchUploader();
      var dropProcessor = new PhotoDropProcessor(photoURLs, hoverNode); 
      window.setTimeout(function foo() {dropProcessor.start();}, 400);
    }

    function getURLFromFile (aFile) {
      var ios = Components.classes["@mozilla.org/network/io-service;1"]
                .getService(Components.interfaces.nsIIOService);
      var fileHandler = ios.getProtocolHandler("file")
                        .QueryInterface(Components.interfaces.nsIFileProtocolHandler);
      return fileHandler.getURLSpecFromFile(aFile);
    }

    function handleFile(file, photoURLs) {
      if (file.isDirectory()) {
        var theEnum = file.directoryEntries;
        while (theEnum.hasMoreElements()) {
          var child = theEnum.getNext().QueryInterface(Components.interfaces.nsIFile);
          if (!child.isHidden()) {
            handleFile(child, photoURLs);
          }
        }
      } else {
        url = getURLFromFile(file);
        if (FlockMedia.isAPhoto(url)) {
          photoURLs.push(url);
        }
        else {
          var stringBundle = FlockMedia.getStringBundle();
          alert(stringBundle.GetStringFromName("flock.photo.upload.error.unsupported").replace("%1",file.leafName));
        }
      }
    }
  },

  getSupportedFlavours: function() {
    var flavors = new FlavourSet();
    flavors.appendFlavour("application/x-moz-file", "nsIFile");
    flavors.appendFlavour("text/x-moz-url");
    flavors.appendFlavour("flock/shelficon");
    flavors.appendFlavour("application/flock-photo", "flockIMediaItem");
    return flavors;
  },

  _isRichVideo: function(aDragSession) {
    var isVideo = false;
    if (aDragSession &&
        aDragSession.isDataFlavorSupported("application/flock-photo"))
    {
      if (!this._richDNDSvc) {
        this._richDNDSvc = Components.classes["@flock.com/rich-dnd-service;1"]
                           .getService(Components.interfaces
                                                 .flockIRichDNDService);
      }
      isVideo = this._richDNDSvc.isSelectionRichVideoContent(aDragSession);
    }
    return isVideo;
  },

  _isHoverOverUploadButton: function(aTarget) {
    return aTarget.nodeName == "toolbarbutton" &&
           aTarget.className == "upload-button";
  }
}
