// 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 ENABLE_DEBUG = true; // switch to turn off slow debug code for production
function DEBUG(x) { if (ENABLE_DEBUG) dump("photoUploader.js: "+x+"\n"); }

const PREF_UPLOADER = "flock.photo.uploader.";
const INITIAL_FILEPATH = "initialPath";
const PU_INITIAL = 1;
const PU_HAS_PHOTOS = 3;
const PU_IMPORTING = 4;

const IMG_EXT = "*.jpg; *.JPG; *.jpeg; *.JPEG; *.gif; *.GIF; *.png; *.PNG; *.bmp; *.BMP";

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import("resource:///modules/FlockUploadUtils.jsm");
Cu.import("resource:///modules/FlockStringBundleHelpers.jsm");

function $(aId) {
  return document.getElementById(aId);
}

function flock_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);
}

var photoUploader = {};
photoUploader.SVC = Cc["@flock.com/media/upload-service;1"]
                    .getService(Ci.flockIPhotoUploadService);

photoUploader.mState = PU_INITIAL;
photoUploader.totalNumImportedPhotos = null;
photoUploader.favsCoop = Cc["@flock.com/singleton;1"]
                         .getService(Ci.flockISingleton)
                         .getSingleton("chrome://flock/content/common/load-faves-coop.js")
                         .wrappedJSObject,
photoUploader.mMetrics = Cc["@flock.com/metrics-service;1"]
                         .getService(Ci.flockIMetricsService);
photoUploader.mLogger = UploadUIUtils.getLogger();
var dropEventHandler = {
  handleEvent: function(event) {
    var sourceNode = nsDragAndDrop.mDragService
                                  .getCurrentSession()
                                  .sourceNode;
    var sourceNodeName = "";
    if (sourceNode) {
      // We have a source node (we should NOT if it was dragged from the OS)
      sourceNodeName = sourceNode.nodeName.toLowerCase();
    }

    if (sourceNodeName != "photoupload") {
      // If it is a photoupload node that is being dragged we do not want
      // to use nsDragAndDrop as an exception will be thrown (there are no
      // data flavours).  Unfortunatly, drag and drop is kind of half used
      // for re-arranging photoupload nodes, this is not ideal but it is how
      // it is.
      nsDragAndDrop.drop(event, photoUploadDNDObserver);
    }
  }
}

photoUploader.accountService = Cc["@flock.com/account-service;1"]
                               .getService(Ci.flockIAccountService);
photoUploader.accountObserver = {
  onAccountAuthenticated: function acctObs_onAccountAuthenticated(aAccount) {
    photoUploader.mLogger.debug("accountObserver: onAccountAuthenticated('"
                                + aAccount.urn + "')");
    var api = aAccount.getService();

    // Only detect auth changes for uploadable accounts
    if (api instanceof Ci.flockIMediaUploadWebService) {
      var servicesMenuList = $("servicesMenuList");
      var selectedAccountUrn = servicesMenuList.value;
      UploadUIUtils.populateServicesPopup(servicesMenuList.firstChild);
      // Reselect the previously selected account
      servicesMenuList.value = selectedAccountUrn;
      photoUploader.serviceChanged();
    }
  },
  onAccountUnauthenticated: function acctObs_onAccountUnauthenticated(aAccount) {
    photoUploader.mLogger.debug("accountObserver: onAccountUnauthenticated('"
                                + aAccount.urn + "')");
    var api = aAccount.getService();

    // Only detect auth changes for uploadable accounts
    if (api instanceof Ci.flockIMediaUploadWebService) {
      var servicesMenuList = $("servicesMenuList");
      var selectedAccountUrn = servicesMenuList.value;
      UploadUIUtils.populateServicesPopup(servicesMenuList.firstChild);
      if (selectedAccountUrn == aAccount.urn) {
        // Select blank item
        servicesMenuList.selectedIndex = -1;
      } else {
        // Reselect the previously selected account
        servicesMenuList.value = selectedAccountUrn;
      }
      photoUploader.serviceChanged();
    }
  },
  onAccountRefreshing: function acctObs_onAccountRefreshing(aAccount) {
    photoUploader.mLogger.debug("accountObserver: onAccountRefreshing('"
                                + aAccount.urn + "')");
  },
  onAccountNoLongerRefreshing: function acctObs_onAccountNoLongerRefreshing(aAccount) {
    photoUploader.mLogger.debug("accountObserver: onAccountNoLongerRefreshing('"
                                + aAccount.urn + "')");
  }
};

photoUploader.checkUploadButton = function photoUploader_checkUploadButton() {
  DEBUG("checkUploadButton()");
  if (this.isReadyForUpload()) {
    $("cmd_doUpload").removeAttribute("disabled");
  } else {
    $("cmd_doUpload").setAttribute("disabled", "true");
  }
};

photoUploader.isReadyForUpload = function photoUploader_isReadyForUpload() {
  DEBUG("isReadyForUpload()");
  // We are ready for upload when an authenticated account has been selected.
  var serviceList = $("servicesMenuList");
  if (serviceList.selectedIndex > -1) {
    var accountURN = serviceList.value;
    if (accountURN) {
      var account = serviceList.selectedItem.svc.getAccount(accountURN);
      if (account.isAuthenticated() && this.getPhotoCount()) {
        return true;
      }
    }
  }

  return false;
};

// Handler for changes to the selected service.
photoUploader.serviceChanged = function photoUploader_serviceChanged() {
  DEBUG(".serviceChanged()");
  photoUploader.SVC.setDefaultService($("servicesMenuList").value);
  photoUploader.setupUI();
  photoUploader.checkUploadButton();
};

photoUploader.load = function() {
  DEBUG("load()");

  this.mMetrics.report("Uploader-Opened", null);
  this.mLogger.init("photoUploader");

  this.SVC.addObserver(this.uploadListener);
  $("flock-photo-upload-slideybox").setListener(this.scrolleyboxListener);

  if ($("batch_is_public").value == "public") {
    $('batch_is_friend').disabled = true;
    $('batch_is_family').disabled = true;
  } else {
    $('batch_is_friend').disabled = false;
    $('batch_is_family').disabled = false;
  }
  
  this.totalNumImportedPhotos = 0;
  this.updateCommandState();
  var servicesMenulist = $("servicesMenuList");
  UploadUIUtils.populateServicesPopup(servicesMenulist.firstChild);
  UploadUIUtils.setDefaultAccount(servicesMenulist);
  this.serviceChanged();
  window.addEventListener("dragdrop", dropEventHandler, true);

  this.accountService.addObserver(this.accountObserver);
}

photoUploader.updatePermInfo = function() {
  var result;
  if ($("batch_is_public").value == "public") {
    result = "(public)";
  } else {
    result = "(private";
    if ($('batch_is_friend').checked)
      result += ", friends";
    if ($('batch_is_family').checked)
      result += ", family";
    result += ")";
  }
  $("batch-permissions-info").value = result;
}

photoUploader.updateTags = function() {
  var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"]
                            .getService(Ci.nsIStringBundleService);
  var stringBundle = stringBundleService
                     .createBundle("chrome://flock/locale/photo/photo.properties");
  var willAlsoApplied = "";
  // Hack to get that executed after the key is processed, not before
  var sync = {
    notify: function (timer) {
      if ($('batch_tags').value != "") {
        willAlsoApplied = stringBundle.GetStringFromName("flock.photo.tag.added");
        var textNode = document.createTextNode(willAlsoApplied + " "
                                               + $("batch_tags").value.replace(/,/g, ", "));
        if ($("global-tags-desc").firstChild)
          $("global-tags-desc").removeChild($("global-tags-desc").firstChild);
        $("global-tags-desc").appendChild(textNode);
        $("global-tags-desc").setAttribute("hidden", "false");
        //window.sizeToContent();
      }
      else
        $("global-tags-desc").setAttribute("hidden", "true");
    }
  }
  var timer = Cc['@mozilla.org/timer;1'].createInstance(Ci.nsITimer);
  timer.initWithCallback(sync, 0, Ci.nsITimer.TYPE_ONE_SHOT);
}

photoUploader.setupUI = function() {
  DEBUG(".setupUI()");
  photoUploader.checkUploadButton();
  var servicesMenulist = $("servicesMenuList");

  if (servicesMenulist.selectedIndex > -1) {
    // Setup the photo properties UI for the selected account
    var api = servicesMenulist.selectedItem.svc;
    photoProperties.setupUIFields(api, servicesMenulist.value);

    var showDetails = api.supportsFeature("description") ||
                      api.supportsFeature("fileName") ||
                      api.supportsFeature("privacy") ||
                      api.supportsFeature("tags") ||
                      api.supportsFeature("notes") ||
                      api.supportsFeature("title");

    if (showDetails) {
      $("batch-tab").removeAttribute("disabled");
      $("photo-functions-container").removeAttribute("flex");
      $("photo-details").setAttribute("flex", "1");
    } else {
      // If there are no detail fields visible, hide the details
      // container and disable the batch tab button.
      $("batch-tab").disabled = true;
      $("uploader-tabs").selectedItem = $("photo-tab");
      $("photo-functions-container").setAttribute("flex", "1");
      $("photo-details").removeAttribute("flex");
    }
  } else {
    // No logged in accounts so setup the photo properties UI for no account selection
    photoProperties.setupUIFields();
    var stringBundle = FlockMedia.getStringBundle();
    servicesMenulist.value = stringBundle.GetStringFromName("flock.photo.service.select");
  }

  if ($("batch_is_public") && $("batch_is_public").value == "public") {
    $("batch-public").setAttribute("selected", "true");
  } else if ($("batch-private")) {
    $("batch-private").setAttribute("selected", "true");
  }
}

photoUploader.updatePrivacy = function() {
  var ispublic = ($("batch_is_public").value == "public");
  $('batch_is_friend').disabled = ispublic;
  $('batch_is_family').disabled = ispublic;

  photoUploader.updatePermInfo();
}

photoUploader.updateBatchLabel =
function photoUploader_updateBatchLabel(aCurrentCount,
                                        aTotalCount) {
  var stringBundle = FlockMedia.getStringBundle();
  labelValue = stringBundle.formatStringFromName("flock.photo.upload.import",
                                                 [aCurrentCount, aTotalCount],
                                                 2);
  document.getElementById("import-photo-label").setAttribute("value", labelValue);
}

photoUploader.unload = function() {
  DEBUG("unload()");

  this.mMetrics.report("Uploader-Close", null);

  // The attribute holds the default value while the property holds the real value.
  // We set the attribute to have it saved in the localStore (using persist).
  $("batch-title").setAttribute("value", $("batch-title").value);
  $("batch-description").setAttribute("value", $("batch-description").value);
  $("batch_is_public").setAttribute("value", $("batch_is_public").value);

  this.SVC.removeObserver(this.uploadListener);

  this.accountService.removeObserver(this.accountObserver);
}

photoUploader.onClose = function() {
  var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
                           getService(Ci.nsIPromptService);
  var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
  var stringBundle = stringBundleService.createBundle("chrome://flock/locale/photo/photo.properties");
    
  var dialogMessage = "";
  var titleMessage = "";
    
  if (this.SVC.isUploading) {
    titleMessage = stringBundle.GetStringFromName("flock.photo.upload.er.title");
    dialogMessage = stringBundle.GetStringFromName("flock.photo.upload.er.msg");

    var rv = promptService.confirm(null, titleMessage, dialogMessage);
    if (rv) {
      this.cancelUpload();
      return true;
    } else {
      return false;
    }
  } else if (this.SVC.isImporting) {
    titleMessage = stringBundle.GetStringFromName("flock.photo.upload.er.title");
    dialogMessage = stringBundle.GetStringFromName("flock.photo.import.er.msg");
    var rv = promptService.confirm(null, titleMessage, dialogMessage);
    if (rv) {
      this.SVC.cancelImport();
      return true;
    } else {
      return false;
    }
  } else 
    return true;
}


photoUploader.cancelUpload = function() {
  DEBUG("cancelUpload()");
  this.mRecentlyCancelled = true;
  this.SVC.cancelUpload();
}

photoUploader.updateCommandState = function(aDisable) {
  DEBUG("updateCommandState("+aDisable+")");
  //first, see if we have uploads
  if (this.mState == PU_IMPORTING) {
    $('flock-photo-import-deck').selectedIndex = 1;
    $("flock-photo-upload-actions").setAttribute("hidden", true);
    $("flock-photo-cancel-actions").setAttribute("hidden", true);
    $("cmd_removePhoto").setAttribute("disabled", true);
    $("cmd_doUpload").setAttribute("disabled", true);
    $("cmd_addFiles").setAttribute("disabled", true);
    $("cmd_launchSettings").setAttribute("disabled", true);
    photoUploader.disableSlideybox();
    this.updateMessage();
    return;
  } else {
    $('flock-photo-import-deck').selectedIndex = 0;
  }
 
  if (photoUploader.SVC.isUploading || aDisable) {
    photoUploader.disableSlideybox();
    photoProperties.clearSelection();
    $("flock-photo-upload-actions").setAttribute("hidden", true);
    $("flock-photo-cancel-actions").removeAttribute("hidden");
    $("cmd_removePhoto").setAttribute("disabled", true);
    $("cmd_doUpload").setAttribute("disabled", true);
    $("cmd_addFiles").setAttribute("disabled", true);
    $("cmd_launchSettings").setAttribute("disabled", true);
    return;
  }
  $("flock-photo-upload-actions").removeAttribute("hidden");
  $("flock-photo-cancel-actions").setAttribute("hidden", true);

  $("cmd_addFiles").removeAttribute("disabled");
  $("cmd_launchSettings").removeAttribute("disabled");

  var count = this.getPhotoCount();
  var selectionCount = this.getSelectionCount();


  if (count == 0) {
    // disable props, upload
    // setup message
    this.mState = PU_INITIAL;
    $("cmd_doUpload").setAttribute("disabled", true);
  }
  else {
    this.mState = PU_HAS_PHOTOS;
    this.checkUploadButton();
  }

  if (selectionCount == 0) {
    $("cmd_removePhoto").setAttribute("disabled", true);
  }
  else {
    $("cmd_removePhoto").removeAttribute("disabled");
  }
  this.updateMessage();
}

photoUploader.updateMessage = function(aOverride) {
  DEBUG("updateMessage("+aOverride+")");
  if (aOverride) {
    this.mState = aOverride;
  }
  var message = "";
  switch(this.mState) {
    case PU_INITIAL:
      $("flock-photo-instructions").removeAttribute("hidden");
      message = $("flock-photo-instructions-message").getAttribute("msgInitial");
    break;

    case PU_HAS_PHOTOS:
      $("flock-photo-instructions").setAttribute("hidden", true);
      message = "";
    break;

    case PU_IMPORTING:
      $("flock-photo-instructions").setAttribute("hidden", true);
      message = "";
    break;
  }
  DEBUG(message + "<<<<<<MESSAGE");
  $("flock-photo-instructions-message").value = message;
}

photoUploader.getPhotoCount = function() {
  return ($("flock-photo-upload-slideybox").getElementsByTagName('slideyitem').length - 1);
}

photoUploader.getSelectionCount = function() {
  var selection = $("flock-photo-upload-slideybox").getSelection();
  return selection.length;
}

photoUploader.getAllPhotoUploads = function() {
  var photouploads = document.getElementsByTagName('photoupload');
  var uploadsArray = Array();
  for (var i = 1; i < photouploads.length; i++) {
    uploadsArray.push(photouploads[i]);
  }
  return uploadsArray;
}

photoUploader.addPhotoFiles = function() {
  DEBUG("addPhotoFiles()");
  var prefs = Cc["@mozilla.org/preferences-service;1"]
          .getService(Ci.nsIPrefService)
          .getBranch(PREF_UPLOADER);

  const nsIFilePicker = Ci.nsIFilePicker;
  var init_dir = Cc["@mozilla.org/file/local;1"].
      createInstance(Ci.nsILocalFile);
  var init_path_pref = getUnicodePref(INITIAL_FILEPATH, prefs);
  var photoUrls = Array();

  if (!init_path_pref) {
    var dirService = Cc["@mozilla.org/file/directory_service;1"]
         .getService(Ci.nsIProperties);

// platform specificness
#ifdef XP_MACOSX
    init_path_pref =dirService.get("Pct", Ci.nsIFile).path;
#elifdef XP_WIN
    init_path_pref = dirService.get("DeskV", Ci.nsIFile).parent.path;
    init_path_pref = init_path_pref + "\\My Pictures";
#else
    init_path_pref = dirService.get("Home", Ci.nsIFile).path;
#endif

    init_dir.initWithPath(init_path_pref);

    if (init_dir.path && init_dir.path.length) {
      init_path_pref = init_dir.path;
    }

    setUnicodePref(INITIAL_FILEPATH, prefs, init_path_pref);

  } else {
    init_dir.initWithPath(init_path_pref);
  }

  var fp = Cc["@mozilla.org/filepicker;1"]
                     .createInstance(nsIFilePicker);

  var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
  var stringBundle = stringBundleService.createBundle("chrome://flock/locale/photo/photo.properties");

  fp.init(window, stringBundle.GetStringFromName("flock.photo.upload.add"), nsIFilePicker.modeOpenMultiple);

  fp.appendFilters(nsIFilePicker.filterAll);
  
  fp.appendFilter(stringBundle.GetStringFromName("flock.photo.upload.imagefilter"),
                  IMG_EXT);
  
  fp.filterIndex = 1;

  var homeDir = null;
  var mypicsPath = null;

  fp.displayDirectory = init_dir;

  if (fp.show() == nsIFilePicker.returnOK && fp.files) {
    var enum = fp.files;
    var item = null;
    var file = null;
    var path = null;
    while (enum.hasMoreElements()) {
      item = enum.getNext();
      file = item.QueryInterface(Ci.nsIFile);
      path = file.path.toLowerCase();
      if ( path.match(/\.jpg$/) ||
           path.match(/\.jpeg$/) ||
           path.match(/\.png$/) ||
           path.match(/\.gif$/) ||
           path.match(/\.mpg$/) ||
           path.match(/\.bmp$/) ) {
        photoUrls.push(flock_getURLFromFile(file));
      }
    }
    var dropProcessor = new PhotoDropProcessor(photoUrls, null);
    dropProcessor.start();
    var lastSelectedDir = file.path.substring(0, file.path.indexOf(file.leafName));
    setUnicodePref(INITIAL_FILEPATH, prefs, lastSelectedDir);
    $('flock-photo-instructions').setAttribute('hidden', true);
  }
}


photoUploader.enableSlideybox = function() {
  $("flock-photo-disable").setAttribute("hidden", true);
}

photoUploader.disableSlideybox = function() {
  $("flock-photo-disable").removeAttribute("hidden");
}

photoUploader.enableGlobal = function(aEnable) {
  if (!$("batch-title"))
    return; // Side-uploader
  $("flock-batch-disable").setAttribute("hidden", aEnable?"true":"false");
}

photoUploader.clearBatch = function() {
  if (!$("batch-title"))
    return; // Side-uploader
  $("batch-title").value = "";
  $("batch-title").setAttribute("value", "");
  $("batch-description").value = "";
  $("batch-description").setAttribute("value", "");
  $('batch_tags').value = "";
  $('batch_tags').setAttribute("value", "");
}

// this may move to slideybox
photoUploader.selectFirstPhoto = function() {
  $("flock-photo-upload-slideybox").firstChild.nextSibling.selected = true;
  $("flock-photo-upload-slideybox").firstChild.nextSibling.focus();
}

photoUploader._openMediaBar = function pu__openMediaBar(aAccount) {
  var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
           .getService(Ci.nsIWindowMediator);
  var win = wm.getMostRecentWindow("navigator:browser");
  if (win) {
    // Open the media bar
    win.mediabar.load(aAccount);
  }
}

/*
 * Load aUrl in a new tab or a new window, according to user preference
 * (it's a general preference)
 */
photoUploader._loadOnePage = function pu__loadOnePage(aUrl) {
  var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
           .getService(Ci.nsIWindowMediator);
  recent = wm.getMostRecentWindow("navigator:browser");

  var linkprefs = Cc["@mozilla.org/preferences-service;1"]
                  .getService(Ci.nsIPrefService)
                  .getBranch("browser.link.");
  var newWindow = linkprefs.getIntPref("open_newwindow");

  if (newWindow == 2) {
    recent.open(aUrl);
  } else {
    var browser = recent.document.getElementById("content");
    browser.loadOneTab(aUrl, null, null, null, false);
  }
}

photoUploader._showSuccessDialog =
function pu__showSuccessDialog(aAccount, aServiceName) {
  const PHOTO_BUNDLE_NAME = "photo/photo";
  var title = flockGetString(PHOTO_BUNDLE_NAME,
                             "flock.photo.upload.success.title");
  var continueLbl = flockGetString(PHOTO_BUNDLE_NAME,
                                   "flock.photo.upload.success.continueLabel");
  var brand = brandGetString("brand", "brandShortName");
  var message = flockGetString(PHOTO_BUNDLE_NAME,
                               "flock.photo.upload.success.message",
                               [brand]);
  var okLbl = flockGetString(PHOTO_BUNDLE_NAME,
                             "flock.photo.upload.success.okLabel");

  var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
                      .getService(Ci.nsIPromptService);
  var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0
            + promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1;
  var check = {
    value: false
  }
  var response = promptService.confirmEx(window,
                                         title, message,
                                         flags, okLbl, continueLbl, "",
                                         null, check);
  if (response == 0) {
    photoUploader._openMediaBar(aAccount);
    window.setTimeout(photoUploader.quit, 0);
  }
}

photoUploader.uploadListener = {
  mErrorOnUpload: false,
  mWindow: window,
  importBatchSize: 0,
  uploadedCount: 0,
  uploadedMedia: [],
  mNewAlbum: false,
  onUploadStart: function (aCurrentUpload, aCount, aMax) {
    DEBUG("uploadListener: onUploadStart()");
    // clear properties selection
    photoUploader.mRecentlyCancelled = false;
    photoUploader.uploadListener.mErrorOnUpload = false;
    photoUploader.updateCommandState();
    photoUploader.enableGlobal(false);

    photoUploader.uploadListener.uploadedCount = aCount;

    var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
    var stringBundle = stringBundleService.createBundle("chrome://flock/locale/photo/photo.properties");

    var msg = stringBundle.GetStringFromName("flock.photo.upload.progress").replace(/%count/, aCount).replace(/%max/, aMax).replace(/%title/,aCurrentUpload.title);

     // -1 because the current photo is not uploaded yet
    var percent = ((aCount - 1)*100) / aMax;
    $('uploading-image').setAttribute("src", aCurrentUpload.thumbFileSpec);
    $('uploading-title').setAttribute("value", msg);
    $('upload-progressmeter').setAttribute("value", percent.toString()+"%");
  },
  onUploadProgress: function (aCurrentProgress) {
    // Why is this now not updating the progress bar?
    DEBUG("uploadListener: onUploadProgress(" + aCurrentProgress + ")");
    $('upload-progressmeter').setAttribute("value", aCurrentProgress.toString()+"%");
  },
  onUpload: function (aCurrentUpload, aCount, aMax) {
  },
  onUploadAdd: function (aCurrentUpload) {
    DEBUG("uploadListener: onUploadAdd()");
    if (!aCurrentUpload) {
      photoProperties.synch();
      photoProperties.invalidate();
    }
    else {
      if (photoProperties.updateSelectedItem(aCurrentUpload)) {
        $(aCurrentUpload.id).parentNode.selected = true;
      }
      photoUploader.updateCommandState();
      if (photoUploader.getPhotoCount() == 1) {
        photoUploader.selectFirstPhoto();
      }
    }
  },
  onUploadRemove: function () {
    DEBUG("uploadListener: onUploadRemove()");
    if (photoUploader.SVC.isUploading) return;
    photoUploader.updateCommandState();
  },
  onUploadComplete: function () {
    DEBUG("uploadListener: onUploadComplete()");
    $('flock-photo-upload-deck').selectedIndex = 0;
    photoUploader.enableSlideybox();
    photoUploader.updateCommandState();
    photoUploader.enableGlobal(true);

    var account;
    var service = $("servicesMenuList").selectedItem.svc;
    var accountURN = $("servicesMenuList").value;
    var serviceName = "unknown";
    if (accountURN) {
      serviceName = service.shortName;
      account = service.getAccount(accountURN);
    }

    if (!this.mErrorOnUpload && !photoUploader.mRecentlyCancelled) {
      var window = this.mWindow;
      var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"]
                           .getService(Ci.nsIWindowMediator);
      var singleUploadWindow = false;
      var allWindows = windowMediator.getEnumerator(null);
      while (allWindows.hasMoreElements()) {
        var win = allWindows.getNext();
        if (win.name == "singlePhotoUploading")
          singleUploadWindow = true;
      }
      if (!singleUploadWindow) {
        photoUploader.SVC.cleanPhotoUploadCache();
      }
      // Only clear the batch fields if successful upload.
      photoUploader.clearBatch();

      var photos = photoUploader.uploadListener.uploadedMedia;
      UploadUIUtils.reportUploadToNewsFeed(account, photos);
      photoUploader._showSuccessDialog(account, serviceName);
    }

    if (this.mErrorOnUpload) {
      // There was an error, we have to remove 1 from uploadedCount as we
      // started the last upload but never finished it.
      photoUploader.uploadListener.uploadedCount--;
    }

    if (photoUploader.uploadListener.uploadedCount > 0) {
      Cc["@flock.com/metrics-service;1"]
      .getService(Ci.flockIMetricsService)
      .report("Uploader-Uploaded",
              [{service: serviceName,
                count: photoUploader.uploadListener.uploadedCount}]);
    }
  },
  onUploadFinalized: function uploadListener_onUploadFinalized(aUpload,aMediaItem) {
    photoUploader.uploadListener.uploadedMedia.push(aMediaItem);
  },
  onUploadError: function (aUpload, aCount, aMax, aError) {
    DEBUG("uploadListener: onUploadError()");
    var errorMessage = aError.errorString;
    // if it's an unknow error display any addition info the server might return
    if (aError.errorCode == aError.PHOTOSERVICE_UNKNOWN_ERROR) {
      errorMessage += "\n\nAdditionally, the server returned the message " + aError.serviceErrorString;
    }
    alert(aError.errorString);
    photoUploader.enableSlideybox();
    photoUploader.enableGlobal(true);
    this.mErrorOnUpload = true;
  },
  onAuthStateChange: function (aState) {
  },
  onMediaImportError: function() {
  },
  onError: function(aError) {
  },
  onUploadCreateError: function(aFile) {
    var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
    var stringBundle = stringBundleService.createBundle("chrome://flock/locale/photo/photo.properties");

    DEBUG("*** onUploadCreateError in photoUploader.js");
    alert(stringBundle.GetStringFromName("flock.photo.upload.error.invalid"));
    photoUploader.updateCommandState();
  },
  onMediaBatchImportStart: function(aBatchSizeNum) {
    this.importBatchSize = aBatchSizeNum;
    photoUploader.updateBatchLabel("0", aBatchSizeNum);
    $('import-progressmeter').removeAttribute('value');
    photoUploader.mState = PU_IMPORTING;
    photoUploader.updateCommandState();
  },
  onMediaBatchImportFinish: function() {
    photoUploader.mState = PU_INITIAL;
    photoUploader.enableSlideybox();
    var firstPhoto = $("flock-photo-upload-slideybox").childNodes.item(1);
    if (firstPhoto) {
      firstPhoto.selected = true;
      firstPhoto.focus();
    }
    photoUploader.updateCommandState();
  },
  onMediaImportFinish: function(aMediaUpload, aCount) {
    var progress = (aCount/this.importBatchSize)*100;
    $('import-progressmeter').setAttribute('value', progress + '%');
  },
  onMediaImportStart: function (aFilename, aNumInBatch) {
    $('import-current-photo-title').setAttribute('value', aFilename);
    photoUploader.updateBatchLabel(aNumInBatch, this.importBatchSize);
    photoUploader.mState = PU_IMPORTING;
    photoUploader.updateCommandState();
  },
}

photoUploader.scrolleyboxListener = {
  onDrop: function(aHoverChild, aSelection) {
    try {
      photoProperties.synch();
      var svc = photoUploader.SVC;
      var hoverChild = aHoverChild;
      if (hoverChild) hoverChild = svc.getPhotoUpload(hoverChild.firstChild.id);
      var ids = new Array();
      for (var i = 0; i < aSelection.length; ++i) {
        ids[i] = aSelection[i].firstChild.id;
      }
      var hoverID = null;
      if (aHoverChild) hoverID = aHoverChild.firstChild.id;

      for (var i = 0; i < ids.length; ++i) {
        if (hoverID && hoverID == ids[i]) continue;
        svc.addPhotoUpload(hoverChild, svc.getPhotoUpload(ids[i]));
      }
      for (var i = 0; i < ids.length; ++i) {
        $(ids[i]).parentNode.selected = true;
      }
    }
    catch(e) {
      alert(e);
    }
  },
  onScrollRight: function() {
  },
  onScrollLeft: function() {
  },
  onSelect: function(aSelection) {
    if (photoUploader.SVC.isUploading) return;
    photoUploader.updateCommandState();
    var uploadItems = Array();
    for (var i = 0; i < aSelection.length; i++) {
      uploadItems.push(aSelection[i].firstChild);
    }
    photoProperties.setSelection(uploadItems, true);
  },
  onRemoveSelection: function(aSelection) {
    var svc = photoUploader.SVC;
    photoUploader.removeSelection(aSelection);
  },
}

photoUploader.cancelImport = function() {
  this.SVC.cancelImport();
}

photoUploader.doUpload = function() {
  DEBUG("doUpload()");
  var params = {
    service: $('servicesMenuList').selectedItem.svc,
    accountURN: $('servicesMenuList').selectedItem.value,
    globalTags: $('batch_tags').value,                            
  };

  // JMC - Extending params to contain all the global settings as well, 
  // They'll get munged into the individual photouploads in the next step
  
  DEBUG("doUpload(): Get the photos");
  params.photoUploads = this.getAllPhotoUploads();
  var rv = UploadUIUtils.launchUploadOptions(params);

  this.uploadListener.mNewAlbum = params.newAlbum;
  this.uploadListener.uploadedMedia = [];

  if (params.launchUploader) {
    $('flock-photo-upload-deck').selectedIndex = 1;
  }

  // Merging tags
  function mergeTags(listA, itemsB) {
    var itemsA = listA.split(",");
    if (listA == "" || listA == ",") {
      itemsA = [];
    }
    for (x in itemsB) {
      if (itemsA.indexOf(x) == -1) {
        itemsA.push(itemsB[x]);
      }
    }
    return itemsA.join(",");
  }

  var globalTagList = params.globalTags.split(",");
  if (params.globalTags == "" || params.globalTags == ",") globalTagList = [];
  var globalPub = ($('batch_is_public').value == "public"); 
  var globalIsFriend = $('batch_is_friend').checked; 
  var globalIsFamily = $('batch_is_family').checked; 
  // set the album id on the photo uploads
  // this should probably be an attribute on the service
  // not each particular photo upload object
  var uploads = this.getAllPhotoUploads();
  for (var i = 0; i < uploads.length; i++) {
    // Apply the global title & description if the image doesn't have one
    if (uploads[i].title == "") {
      uploads[i].title = $("batch-title").value;
    }
    if (uploads[i].description == "") {
      uploads[i].description = $("batch-description").value;
    }

    uploads[i].album = params.albumId;
    uploads[i].tags = mergeTags(uploads[i].tags, globalTagList);
    if (uploads[i].privacy_use_batch == "true") {
      uploads[i].is_public = globalPub ? "true" : "false";
      if (globalPub) {
        uploads[i].is_friend = "false";
        uploads[i].is_family = "false";
      } else {
        uploads[i].is_friend = globalIsFriend ? "true" : "false";
        uploads[i].is_family = globalIsFamily ? "true" : "false";
      }
    } else if (uploads[i].is_public == "true") {
      uploads[i].is_friend = "false";
      uploads[i].is_family = "false";
    }
    var flockPhotoUpload = Cc["@flock.com/photo-upload;1"]
                           .createInstance(Ci.flockIPhotoUpload);
    flockPhotoUpload.id = uploads[i].id;
    for each (var attr in FlockUploadUtils.ATTRIBUTES) {
      flockPhotoUpload[attr] = uploads[i][attr];
    }
    this.SVC.savePhotoUpload(flockPhotoUpload);
  }

  if (params.apiName) {
    window.setTimeout(this.reallyDoUpload, 0, params.service.contractId);
    this.updateCommandState(true);
  }
}

photoUploader.reallyDoUpload = function(aServiceId) {
  DEBUG("reallyDoUpload('"+aServiceId+"')");
  var api = Cc[aServiceId].getService(Ci.flockIMediaUploadWebService);
  photoUploader.SVC.upload(api);
}

photoUploader.removeSelection = function(aSelection) {
  DEBUG("removeSelection()");
  
  if (!aSelection) {
    aSelection = $("flock-photo-upload-slideybox").getSelection();
  }
  this.mMetrics.report("Uploader-RemovePhoto", aSelection.length);

  photoProperties.clearSelection();
  var inst = this;
  var domFxListener = {
    onComplete: function(aElement) {
      var spacer = document.createElement('spacer');
      spacer.setAttribute('width', '75');
      aElement.parentNode.parentNode.insertBefore(spacer, aElement.parentNode);
      
      collapseListener = {
        onComplete: function(aElement) {
          aElement.parentNode.removeChild(aElement);
        },
      }
      gDomFx.collapse(spacer, collapseListener, "horizontal", "75");
      inst.SVC.removePhotoUpload(aElement.id);
    },
  }
  
  for (var i = 0; i < aSelection.length; ++i) {
    gDomFx.fadeOut(aSelection[i].firstChild, domFxListener);  
    aSelection[i].selected = false;
  }
  
  var newSelected = aSelection[aSelection.length-1].nextSibling || aSelection[0].previousSibling;
  if (newSelected) {
    newSelected.selected = true;
    newSelected.focus();
    // todo -- make this smoothly scroll to this new element
    $("flock-photo-upload-slideybox").ensureElementIsVisible(newSelected);
  }
  return;
  
}

photoUploader.startUploadFlow = function() {
  DEBUG("startUploadFlow()");
  var inst = this;
  var accountURN = $("servicesMenuList").value;
  var service = $("servicesMenuList").selectedItem.svc;
  if (accountURN) {
    DEBUG("startUploadFlow(): using service: "+service.title);
    if (service.getAuthenticatedAccount()) {
      DEBUG("startUploadFlow(): service "+service.title+" is logged in");
      this.doUpload();
    } else {
      DEBUG("startUploadFlow(): service "+service.title+" is logged out");
      var loginListener = {
        onSuccess: function(aSubject, aTopic) {
          DEBUG("startUploadFlow(): loginListener: onAuth()");
          inst.doUpload();
        },
        onError: function(aError) {
          DEBUG("startUploadFlow(): loginListener: onError(): "+aError.errorString);
        },
      }
      var stringBundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
      var stringBundle = stringBundleService.createBundle("chrome://flock/locale/photo/photo.properties");

      // there is a bug in the apimanager which causes multiple state changes
      // which prevents us to use it -- for now call the login on the
      // photoservice directly
      DEBUG("startUploadFlow(): logging in to service "+service.title);
      service.getAccount(accountURN).login(loginListener);
    }
  } else {
    var params = {};
    params.hasValidSvc = false;
    rv = UploadUIUtils.launchSettings(params);
    if (params.hasValidSvc) {
      this.doUpload();
    }
  }
}

photoUploader.fillFriendsList =
function pu_fillFriendsList(aPopupContent,
                            aXPercent,
                            aYPercent) {
  var accountURN = $("servicesMenuList").value;
  var _coop = photoUploader.favsCoop;
  var children = aPopupContent.childNodes;

  function _onclick(aEvent) {
    $("notes").add(aXPercent.toFixed(1),
                   aYPercent.toFixed(1),
                   aEvent.target.getAttribute("uid"),
                   aEvent.target.getAttribute("name"));
    $("tagPopup").hidePopup();
  }

  function _findPosition(aName) {
    var low = 2; // Ignore "Me" and the separator
    var high = children.length - 1;
    var ref;
    while (low < high) {
      var mid = Math.floor((low + high) / 2);
      ref = children.item(mid);
      if (ref.getAttribute("value") > aName) {
        high = mid;
      } else {
        low = mid + 1;
      }
    }
    ref = children.item(low);
    if (low == high) {
      if (aName > ref.getAttribute("value")) {
        ref = children.item(low + 1);
      }
    }
    return ref;
  }

  // add "me" to top of the tag list if not already tagged
  var coopAct = _coop.get(accountURN);
  if (coopAct && !$("notes").isUidTagged(coopAct.accountId)) {
    var meName = coopAct.name;
    var me = document.createElement("label");
    me.setAttribute("class", "person");
    me.setAttribute("uid", coopAct.accountId);
    me.setAttribute("name", meName);

    var sb = Cc["@mozilla.org/intl/stringbundle;1"]
             .getService(Ci.nsIStringBundleService)
             .createBundle("chrome://flock/locale/photo/photo.properties");
    me.setAttribute("value", sb.formatStringFromName("flock.photo.upload.me",
                                                     [meName],
                                                     1));
    me.onclick = _onclick;
    aPopupContent.appendChild(me);

    var divider = document.createElement("box");
    divider.setAttribute("class", "divider");
    aPopupContent.appendChild(divider);
  }

  var friendsEnum = coopAct.friendsList.children.enumerate();
  while (friendsEnum.hasMoreElements()) {
    var friend = friendsEnum.getNext();
    var accountId = friend.accountId;
    // add Facebook friend to the tag list if not already tagged
    if (!$("notes").isUidTagged(accountId)) {
      var name = friend.name;
      var element = document.createElement("label");
      element.setAttribute("class", "person");
      element.setAttribute("uid", accountId);
      element.setAttribute("name", name);
      element.setAttribute("value", name);
      element.onclick = _onclick;

      var ref = _findPosition(name);
      // appends to list if ref is null
      aPopupContent.insertBefore(element, ref);
    }
  }
}

function getUnicodePref(prefName, prefBranch) {
  if (prefBranch.prefHasUserValue(prefName)) {
    return prefBranch.getComplexValue(prefName, Ci.nsISupportsString).data;
  }
  return null;
}

photoUploader.quit = function pu_quit() {
  window.close();
}

function setUnicodePref(prefName, prefBranch, prefValue) {
  var sString = Cc["@mozilla.org/supports-string;1"]
                          .createInstance(Ci.nsISupportsString);
  sString.data = prefValue;
  prefBranch.setComplexValue(prefName, Ci.nsISupportsString, sString);
}

function openHelp() {
  window.open('http://help.flock.com/content.php?title=Uploading___organizing_online_photos', 'FlockHelp', 'width=555,height=545,resizable,scrollbars');
}
