// Make sure the XWiki 'namespace' exists.
if(typeof(XWiki) == 'undefined') {
  XWiki = new Object();
}

// Make sure the widgets 'namespace' exists.
if(typeof(XWiki.widgets) == 'undefined') {
  XWiki.widgets = new Object();
}

XWiki.widgets.ModalPopup = Class.create({
  /** Configuration. */
  options : {
    title : "",
    displayCloseButton : true,
    screenColor : "#000",
    borderColor : "#333",
    titleColor : "#333",
    backgroundColor : "#EEE",
    screenOpacity : "0.5",
    verticalPosition : "center",
    horizontalPosition : "center"
  },
  /** Constructor. Registers the key listener that pops up the dialog. */
  initialize : function(content, shortcuts, options) {
    /** Shortcut configuration. Action name -&gt; {method: function(evt), keys: string[]}. */
    this.shortcuts = {
      "show" : { method : this.createDialog, keys : ['Ctrl+G', 'Meta+G']},
      "close" : { method : this.closeDialog, keys : ['Esc']}
    },

    this.content = content || "Hello world!";
    // Add the new shortcuts
    Object.extend(this.shortcuts, shortcuts || { });
    // Add the custom options
    Object.extend(this.options, options || { });
    // Register a shortcut for showing the dialog.
    this.registerShortcuts("show");
  },
  /** Create the dialog, if it is not already loaded. Otherwise, just make it visible again. */
  createDialog : function(event) {
    Event.stop(event);
    // Only do this if the dialog is not already active.
    if (!XWiki.widgets.ModalPopup.active) {
      XWiki.widgets.ModalPopup.active = true;
      if (!this.dialog) {
        // The dialog wasn't loaded, create it.
        this.dialog = new Element('div', {'class': 'xdialog-modal-container'});
        // A full-screen semi-transparent screen covering the main document
        var screen = new Element('div', {'class': 'xdialog-screen'}).setStyle({
          opacity : this.options.screenOpacity,
          backgroundColor : this.options.screenColor
        });
        this.dialog.update(screen);
        // The dialog chrome
        this.dialogBox = new Element('div', {'class': 'xdialog-box'});
        // Insert the content
        this.dialogBox.update(this.content);
        // Add the dialog title
        if (this.options.title) {
          var title = new Element('div', {'class': 'xdialog-title'}).update(this.options.title);
          title.setStyle({"color" : this.options.titleColor});
          this.dialogBox.insertBefore(title, this.dialogBox.firstChild);
        }
        // Add the close button
        if (this.options.displayCloseButton) {
          var closeButton = new Element('div', {'class': 'xdialog-close', 'title': 'Close'}).update("X");
          closeButton.setStyle({"color": this.options.titleColor});
          closeButton.observe("click", this.closeDialog.bindAsEventListener(this));
          this.dialogBox.insertBefore(closeButton, this.dialogBox.firstChild);
        }
        this.dialog.appendChild(this.dialogBox);
        this.dialogBox.setStyle({
          "textAlign": "left",
          "borderColor": this.options.borderColor,
          "backgroundColor" : this.options.backgroundColor
        });
        switch(this.options.verticalPosition) {
          case "top":
            this.dialogBox.setStyle({"top": "0"});
            break;
          case "bottom":
            this.dialogBox.setStyle({"bottom": "0"});
            break;
          default:
            // TODO: smart alignment according to the actual height
            this.dialogBox.setStyle({"top": "50%"});
            break;
        }
        switch(this.options.horizontalPosition) {
          case "left":
            this.dialog.setStyle({"textAlign": "left"});
            break;
          case "right":
            this.dialog.setStyle({"textAlign": "right"});
            break;
          default:
            this.dialog.setStyle({"textAlign": "center"});
            this.dialogBox.setStyle({"margin": "auto"});
          break;
        }
        // Append to the end of the document body.
        document.body.appendChild(this.dialog);
      }
      // Display it.
      this.showDialog();
    }
  },
  /** Called when the dialog is displayed. Enables the key listeners and gives focus to the (cleared) input. */
  showDialog : function() {
    // Start listening to keyboard events
    this.attachKeyListeners();
    // In IE, position: fixed does not work.
    if (Prototype.Browser.IE) {
      this.dialog.setStyle({top : document.viewport.getScrollOffsets().top + "px"});
      Event.observe(window, "scroll", this.onScroll.bindAsEventListener(this));
    }
    // Display the dialog
    this.dialog.show();
  },
  onScroll : function(event) {
    this.dialog.setStyle({top : document.viewport.getScrollOffsets().top + "px"});
  },
  /** Called when the dialog is closed. Disables the key listeners, hides the UI and re-enables the 'Show' behavior. */
  closeDialog : function(event) {
    Event.stop(event);
    // Hide the dialog, without removing it from the DOM.
    this.dialog.hide();
    // Stop the UI shortcuts (except the initial Show Dialog one).
    this.detachKeyListeners();
    // Re-enable the 'show' behavior.
    XWiki.widgets.ModalPopup.active = false;
  },
  /** Enables all the keyboard shortcuts, except the one that opens the dialog, which is already enabled. */
  attachKeyListeners : function() {
    for (var action in this.shortcuts) {
      if (action != "show") {
        this.registerShortcuts(action);
      }
    }
  },
  /** Disables all the keyboard shortcuts, except the one that opens the dialog. */
  detachKeyListeners : function() {
    for (var action in this.shortcuts) {
      if (action != "show") {
        this.unregisterShortcuts(action);
      }
    }
  },
  /**
   * Enables the keyboard shortcuts for a specific action.
   *
   * @param {String} action The action to register
   * {@see #shortcuts}
   */
  registerShortcuts : function(action) {
    var shortcuts = this.shortcuts[action].keys;
    var method = this.shortcuts[action].method;
    for (var i = 0; i < shortcuts.size(); ++i) {
      if (Prototype.Browser.IE || Prototype.Browser.WebKit) {
        shortcut.add(shortcuts[i], method.bindAsEventListener(this, action), {type: 'keyup'});
      } else {
        shortcut.add(shortcuts[i], method.bindAsEventListener(this, action), {type: 'keypress'});
      }
    }
  },
  /**
   * Disables the keyboard shortcuts for a specific action.
   * 
   * @param {String} action The action to unregister {@see #shortcuts}
   */
  unregisterShortcuts : function(action) {
    for (var i = 0; i < this.shortcuts[action].keys.size(); ++i) {
      shortcut.remove(this.shortcuts[action].keys[i]);
    }
  },
  createButton : function(type, text, title, id) {
    var wrapper = new Element("span", {"class" : "buttonwrapper"});
    var button = new Element("input", {
      "type" : type,
      "class" : "button",
      "value" : text,
      "title" : title,
      "id" : id
    });
    wrapper.update(button);
    return wrapper;
  }
});
/** Whether or not the dialog is already active (or activating). */
XWiki.widgets.ModalPopup.active = false;

// When the document is loaded, enable the keyboard listener that triggers the dialog.
// document.observe("xwiki:dom:loaded", function() {
//   new XWiki.widgets.ModalPopup("An example dialog",
//     { "show" : { method : "this.createDialog", keys : ['Ctrl+Y', 'Meta+Y']} },
//     { title: "Example", titleColor: "#369", borderColor: "#369", screenColor: "#FFF" }
//   );
// });
