var XWiki = (function(XWiki) {
  /** Handles the gallery buttons directly in the current page without reloading the window. */
  XWiki.AttachmentPicker = Class.create({
    /**
     * Constructor.
     *
     * @param property the property being edited, as the containing div with class="attachment-picker"
     * @param dialog the modal dialog where the gallery was loaded
     */
    initialize : function(property, dialog) {
      this.property = property;
      this.dialog = dialog;
      this.gallery = dialog.dialogBox;
      if (!this.property.down('input')) {
        this.directSave = true;
      }
      this.defaultValue = '';
      var defaultValueElement = this.gallery.down('.gallery_emptyChoice .gallery_attachmenttitle');
      if (defaultValueElement) {
        this.defaultValue = defaultValueElement.title;
      }
      this.defaultImageSource = '';
      var defaultImage = this.gallery.down('.gallery_emptyChoice.gallery_image img');
      if (defaultImage) {
        this.defaultImageSource = defaultImage.src.replace(/\?.*$/, '');
      }
      this.filterFormUpload();
      this.addDeleteListeners();
      this.addSelectListeners();
      this.updateCurrentSelection();
      this.addCloseListener();
      var img = this.property.down('img');
      if (img) {
        img.observe('load', function() {img.up('div').removeClassName('hidden');});
        img.observe('error', function() {img.up('div').addClassName('hidden');});
      }
    },
    /**
     * Catches the upload form submission and stops it if the selected file is not of the accepted types (or not selected at all),
     * and saves the underlying form (if any) so that any unsaved changes won't be lost.
     */
    filterFormUpload : function() {
      this.gallery.select('.uploadAttachment input[type="file"]').each(function(fileInput) {
        fileInput.__allowedExtensions = fileInput.title.toLowerCase().replace(/\s*[,|; ]\s*/g, " ").strip();
        if (fileInput.__allowedExtensions != '') {
          fileInput.__allowedExtensions = fileInput.__allowedExtensions.split(" ");
        } else {
          fileInput.__allowedExtensions = false;
        }
      });
      this.gallery.select(".uploadAttachment").invoke('observe', 'submit', function(event) {
        event.stop();
        var uploadForm = event.element();
        var hasErrors = false;
        uploadForm.select('input[type="file"]').each(function(fileInput) {
          if (fileInput.value == '') {
            new XWiki.widgets.Notification("Please choose a file to upload", 'error');
            hasErrors = true;
          } else if (fileInput.__allowedExtensions && fileInput.__allowedExtensions.indexOf(this.getFileExtension(fileInput.value)) == -1) {
            new XWiki.widgets.Notification("Unsupported file format", 'error');
            hasErrors = true;
          }
        }.bind(this));
        // No form submission by AJAX right now, because file uploads can't be done this way without HTML5, this is future work
        // Save the document before submitting, since the current form data will be lost otherwise
        if (!hasErrors) {
          if (this.directSave) {
            uploadForm.submit();
          } else {
            // FIXME This fails in HTML5, will deal with it later:
            // this.property.down('input').value = uploadForm.down('input[type="file"]').value;
            // uploadForm.xredirect.value = window.location.pathname;
            document.observe('xwiki:document:saved', function() {
              new XWiki.widgets.Notification("Uploading...", 'inprogress');
              uploadForm.submit();
            })
            document.fire('xwiki:actions:save', {'continue': true, form: this.property.up('form')});
          }
        }
      }.bindAsEventListener(this));
    },
    getFileExtension : function(filename) {
      var fpath = filename.replace('\\', '/');
      var pieces = fpath.split('/');
      if (pieces.length == 0) {
        return null;
      }
      var basename = pieces[pieces.length-1];
      pieces = basename.split('.');
      return pieces[pieces.length-1].toLowerCase();
    },

    /** Catch attachment delete requests. */
    addDeleteListeners : function() {
      this.gallery.select('.gallery_actions .tool.delete').invoke('observe', 'click', this.onDelete.bindAsEventListener(this));
    },

    /** Catch attachment selection requests. */
    addSelectListeners : function() {
      this.gallery.select('.gallery_actions .tool.select').invoke('observe', 'click', this.onSelect.bindAsEventListener(this));
    },

    /** AJAX deletion of attachments. */
    onDelete : function(event) {
      event.stop();
      deleteTool = event.element();
      if (!deleteTool.disabled) {
        new XWiki.widgets.ConfirmedAjaxRequest(
          deleteTool.readAttribute('href'),
          {
            onCreate : function() { deleteTool.disabled = true },
            onSuccess : function() {
              var attachmentBox = deleteTool.up('.gallery_attachmentbox');
              if (attachmentBox) {
                if (attachmentBox.hasClassName('current')) {
                   this.updateAttachment(this.defaultValue, this.defaultImageSource);
                   if (this.gallery.down('.gallery_emptyChoice')) {
                     this.gallery.down('.gallery_emptyChoice').addClassName('current');
                   }
                   // Disable the replace feature because there's no selection.
                   var fileNameInput = this.gallery.down('input[type="checkbox"][name="filename"]');
                   fileNameInput.disabled = true;
                   // Empty the displayed selected file name.
                   fileNameInput.up('label').down('strong').update('');
                   if (!this.directSave) {
                     this.property.down('input').value = this.defaultValue;
                   }
                }
                attachmentBox.remove();
              }
            }.bind(this),
            onComplete : function() {
              deleteTool.disabled = false;
            }
          },
          {
            confirmationText: "Are you sure you want to delete this attachment?",
            progressMessageText : "Deleting...",
            successMessageText : "Attachment deleted",
            failureMessageText : "Failed to delete attachment:"
          }
        );
      }
    },

    /** Update the property with the selected value without reloading the page. */
    onSelect : function(event) {
      event.stop();
      var targetElement = event.element();
      var attachmentName = targetElement.up('.gallery_attachmentbox').down('.gallery_attachmenttitle').title;
      var imageSource = targetElement.up('.gallery_attachmentbox.gallery_image');
      if (imageSource) {
        imageSource = imageSource.down('.gallery_attachmentframe img');
        if (imageSource) {
          imageSource = imageSource.src.replace(/\?.*$/, '');
        }
      }
      if (!imageSource) {
        imageSource = '';
      }
      if (this.directSave) {
        // save via ajax
        if (!targetElement.disabled) {
          new Ajax.Request(event.element().href, {
            onCreate : function() {
              targetElement.disabled = true;
              targetElement._x_notif = new XWiki.widgets.Notification("Sending request...", 'inprogress');
            },
            onSuccess : function () {
              targetElement._x_notif.hide();
              // on success, update image
              this.updateAttachment(attachmentName, imageSource);
              this.dialog.closeDialog();
            }.bindAsEventListener(this),
            onFailure : function(response) {
              var failureReason = response.statusText;
              if (response.statusText == '' /* No response */ || response.status == 12031 /* In IE */) {
                failureReason = 'Server not responding';
              }
              if (targetElement._x_notif) {
                targetElement._x_notif.replace(new XWiki.widgets.Notification("Failed:" + failureReason, "error"));
              } else {
                new XWiki.widgets.Notification(this.interactionParameters.failureMessageText + failureReason, "error");
              }
            },
            on1223 : function(response) {
              response.request.options.onSuccess(response);
            },
            on0 : function(response) {
              response.request.options.onFailure(response);
            },
            onComplete : function() {
              targetElement.disabled = false;
            }
          });
        }
      } else {
        this.updateAttachment(attachmentName, imageSource);
        this.property.down('input').value = attachmentName;
        this.dialog.closeDialog();
      }
    },

    /** Update the property display. */
    updateAttachment : function(attachmentName, imageSource) {
      var img = this.property.down('img');
      if (img) {
        img.src = img.src.replace(/^[^\?]+($|\?)/, imageSource + "$1");
        var link = img.up('a');
        if (link) {
          link.href = link.href.replace(/^[^\?]+($|\?)/, imageSource + "$1");
        }
      } else {
        var displayed = this.property.down('.displayed');
        if (displayed) {
          displayed.update(attachmentName);
          var link = displayed.up('a');
          if (link) {
            link.href = link.href.replace(/^[^\?]+($|\?)/, attachmentName + "$1");
          }
        }
      }
    },

    /** Update the gallery to reflect the currently selected value. */
    updateCurrentSelection : function() {
      if (!this.directSave) {
        var selectedName =  this.property.down('input').value;
        var selectedElement = this.gallery.down('.gallery_attachmenttitle[title="' + selectedName.replace('"', '\\22 ') + '"]');
        if (selectedElement) {
          selectedElement = selectedElement.up('.gallery_attachmentbox');
        } else {
          selectedElement = this.gallery.down('.gallery_emptyChoice');
        }
        if (!selectedElement.hasClassName('current')) {
          this.gallery.select('.gallery_attachmentbox.current .tool.select').invoke('removeClassName', 'hidden');
          this.gallery.select('.gallery_attachmentbox.current').invoke('removeClassName', 'current');
          selectedElement.addClassName('current');
        }
        selectedElement.down('.tool.select').addClassName('hidden');
      } else {
        this.gallery.down('.current .tool.select').addClassName('hidden');
      }
    },
    addCloseListener : function () {
      var closeButton = $('attachment-picker-close');
      if (closeButton) {
        closeButton.observe('click', function(event) {
          event.stop();
          this.dialog.closeDialog();
        }.bindAsEventListener(this));
      }
    }
  });

  var loading = new Element('div', {'class' : 'imgcenter'}).update("<img src=\"../../../resources/icons/xwiki/ajax-loader-large.gif\"/>");
  var dialog;

  /* Hook onto the picker buttons so that the gallery is loaded via AJAX in a modal dialog. */
  document.observe('xwiki:dom:loaded', function() {
    $$('.attachment-picker-start').invoke('observe', 'click', function(event) {
      event.stop();
      var targetElement = event.element();
      var url = targetElement.href;
      if (url.indexOf('?') < 0) {
        url += '?';
      }
      url += "&xpage=plain";
      dialog = new XWiki.widgets.ModalPopup(
        loading, {}, {
          'verticalPosition' : 'top',
          'removeOnClose' : true,
          'title' : "Attachments"
        }
      );
      dialog.shortcuts.close.keys = [];
      dialog.showDialog();
      dialog.dialog.down().setStyle({position: "fixed"});
      dialog.dialog.setStyle({top: document.viewport.getScrollOffsets().top + "px", position: "absolute"});
      dialog.dialogBox.setStyle({overflow: "hidden", width: "80%", margin: "0 10%"});
      new Ajax.Updater(loading.up(), url, {
        onComplete : function() {
          // Play nice with the Lightbox widget
          if (window.gallery_lb) {
            window.gallery_lb.updateImageList();
          }
          // Manually convert the special rel values into target attributes for the newly inserted content (rel="_something" => target="something")
          if (typeof (XWiki.fixLinksTargetAttribute) == 'function') {
            // Trick the function into updating link targets in edit mode; normally the conversion only takes place in view mode
            var __tmp = XWiki.contextaction;
            XWiki.contextaction = 'view';
            XWiki.fixLinksTargetAttribute(dialog.dialog);
            XWiki.contextaction = __tmp;
          }
          new XWiki.AttachmentPicker(targetElement.up('.attachment-picker'), dialog);
        }
      });
    });
  });
  return XWiki;
}(XWiki || {}));
XWiki.widgets.ModalPopup.prototype.showDialog = function(event) {
  if (event) {
    Event.stop(event);
  }
  // Only do this if the dialog is not already active.
  if (!this.active) {
    this.active = true;
    if (!this.dialog) {
      // The dialog wasn't loaded, create it.
      this.createDialog();
    }
    // Start listening to keyboard events
    this.attachKeyListeners();
    // Display the dialog
    this.dialog.show();
  }
};
XWiki.widgets.ModalPopup.prototype.closeDialog = function(event) {
  if (event) {
    Event.stop(event);
  }
  // Call optional callback
  this.options.onClose.call(this);
  // Hide the dialog, without removing it from the DOM.
  this.dialog.hide();
  if (this.options.removeOnClose) {
    this.dialog.remove();
  }
  // Stop the UI shortcuts (except the initial Show Dialog one).
  this.detachKeyListeners();
  // Re-enable the 'show' behavior.
  this.active = false;
}

