// Make sure the XWiki 'namespace' exists.

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

/**
 * Javascript enhancements for the blog categories management.
 */
XWiki.blog.Categories = Class.create({
  categoriesSelector : ".blog-category-level",
  activeForm: false,
  /** Constructor. Adds all the JS improvements of the categories tree. */
  initialize : function() {
    if ($$(".blog-categories-list")) {
      this.addDeleteListener();
      this.addAddSubcategoryListener();
      this.addAddCategoryListener();
      this.addRenameListener();
    }
  },
  activateForm : function(form) {
    if (this.activeForm) {
      this.activeForm.hide();
    }
    form.show();
    this.activeForm = form;
    form.down('input[type=text]').focus();
  },
  /**
   * Ajax category rename.
   * For all buttons, listen to "click", and make ajax request to rename the category.
   */
  addRenameListener : function() {
    $$(".blog-category-level").each(function(item) {
      // Prototype bug in Opera: $$(".blog-category-level a.rename") returns only the first result.
      // Quick fix until Prototype 1.6.1 is integrated.
      item = item.down('a.rename');
      if (!item) {
        return;
      }
      item.observe('click', function(event) {
        item.blur();
        event.stop();
        if (item.disabled) {
          // Do nothing if the button was already clicked and it's waiting for a response from the server.
          return;
        } else {
          this.createRenameForm(item);
        }
      }.bindAsEventListener(this));
    }.bind(this));
  },
  createRenameForm : function (item) {
    var parent = item.up('.blog-categories-list');
    if (!parent._x_rename_form) {
      if (!parent.disabled) {
        new Ajax.Request(
          "/xwiki/bin/view/Blog/ManageCategories?xpage=plain&display=renameForm&ajax=1",
          {
            onCreate : function () {
              // ignore "cascade" clicks
              parent.disabled = true;
              parent.notification = new XWiki.widgets.Notification("Fetching form...", "inprogress");
            },
            onSuccess : function (response) {
              var container = new Element("div");
              container.update(response.responseText);
              parent._x_rename_form = container.down('form');
              this.ajaxifyRenameForm(parent._x_rename_form);
              this.insertRenameForm(item, parent._x_rename_form);
            }.bind(this),
            onFailure : function (response) {
              new XWiki.widgets.Notification(response.responseText || "Server not responding", "error");
            },
            // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
            on0 : function(response) {
              response.request.options.onFailure(response);
            },
            onComplete : function () {
              parent.disabled = false;
              parent.notification.hide();
            }
          }
        );
      }
    } else {
      this.insertRenameForm(item, parent._x_rename_form);
    }
  },
  insertRenameForm : function(item, form) {
    form._x_item = item;
    item.up('.blog-category-tools').insert({after : form});
    var category = form.down('input[name=category]');
    category.value = decodeURIComponent(item.href.substring(item.href.indexOf('category=') + 9).replace(/\+/g, ' '));
    this.activateForm(form);
  },
  ajaxifyRenameForm : function(form) {
    form.setAttribute('autocomplete', 'off');
    form.down('input[type=text]').setAttribute('autocomplete', 'off');
    form.down('input[type=text]').setAttribute('autocomplete', 'off');
    form.observe('submit', function(event) {
      event.stop();
      form.down('input[type=text]').focus();
      if (form.newCategoryName.value != '') {
        new Ajax.Request(
          form.action + '?ajax=1&xpage=plain&display=list&' + form.serialize(),
          {
            onCreate : function () {
              // ignore "cascade" clicks
              form.disable();
              form.notification = new XWiki.widgets.Notification("Renaming category...", "inprogress");
            },
            onSuccess : function (response) {
              $$(".blog-categories-list").first().replace(response.responseText);
              this.initialize();
              form.reset();
            }.bind(this),
            onFailure : function (response) {
              new XWiki.widgets.Notification(response.responseText || "Server not responding", "error");
            },
            onComplete : function () {
              form.enable();
              form.notification.hide();
            },
            on403 : function(response) {
              new XWiki.widgets.Notification("You are not allowed to create the target page", "error");
            },
            on404 : function(response) {
              new XWiki.widgets.Notification("Invalid category, please refresh the page to update the category tree", "error");
            },
            on409 : function(response) {
              new XWiki.widgets.Notification("Target page already exists, please choose a different name", "error");
            },
            // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
            on0 : function(response) {
              response.request.options.onFailure(response);
            }
          }
        );
      }
    }.bindAsEventListener(this));
    form.down('a').observe('click', function(event) {
      this.reset();
      event.stop();
    }.bindAsEventListener(form));
    form.observe('reset', function() {
      form.hide();
    });
  },
  /**
   * Ajax category creation.
   * For all buttons, listen to "click", and make ajax request to add the category.
   */
  addAddSubcategoryListener : function() {
    $$(".blog-category-level").each(function(item) {
      // Prototype bug in Opera: $$(".blog-category-level a.add-subcategory") returns only the first result.
      // Quick fix until Prototype 1.6.1 is integrated.
      item = item.down('a.add-subcategory');
      if (!item) {
        return;
      }
      item.observe('click', function(event) {
        item.blur();
        event.stop();
        if (item.disabled) {
          // Do nothing if the button was already clicked and it's waiting for a response from the server.
          return;
        } else {
          this.createAddSubcategoryForm(item);
        }
      }.bindAsEventListener(this));
    }.bind(this));
  },
  addAddCategoryListener : function() {
    $$(".blog-add-category-label a").each(function(item) {
      item.observe('click', function(event) {
        item.blur();
        event.stop();
        this.createAddSubcategoryForm(item);
      }.bindAsEventListener(this));
    }.bind(this));
  },
  createAddSubcategoryForm : function (item) {
    var parent = item.up('.blog-categories-list');
    if (!parent._x_add_form) {
      if (!parent.disabled) {
        new Ajax.Request(
          "/xwiki/bin/view/Blog/ManageCategories?xpage=plain&display=addForm&ajax=1",
          {
            onCreate : function () {
              // ignore "cascade" clicks
              parent.disabled = true;
              parent.notification = new XWiki.widgets.Notification("Fetching form...", "inprogress");
            },
            onSuccess : function (response) {
              var container = new Element("div");
              container.update(response.responseText);
              parent._x_add_form = container.down('form');
              this.ajaxifyAddForm(parent._x_add_form);
              this.insertAddForm(item, parent._x_add_form);
            }.bind(this),
            onFailure : function (response) {
              new XWiki.widgets.Notification(response.responseText || "Server not responding", "error");
            },
            // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
            on0 : function(response) {
              response.request.options.onFailure(response);
            },
            onComplete : function () {
              parent.disabled = false;
              parent.notification.hide();
            }
          }
        );
      }
    } else {
      this.insertAddForm(item, parent._x_add_form);
    }
  },
  insertAddForm : function(item, form) {
    form._x_item = item;
    var select = form.down('select');
    select.selectedIndex = 0;
    if (item.hasClassName('tool')) {
      item.up('.blog-category-tools').insert({after : form});
      var selector = 'option[value=\'' + decodeURIComponent(item.href.substring(item.href.indexOf('parentCategory=') + 15).replace(/\+/g, ' ')).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + '\']';
      var option = select.down(selector);
      if (option) {
        select.selectedIndex = option.index;
      }
      select.up('label').hide();
    } else {
      item.up('ul').insert({after : form});
      select.up('label').show();
    }
    this.activateForm(form);
  },
  ajaxifyAddForm : function(form) {
    form.setAttribute('autocomplete', 'off');
    form.down('input[type=text]').setAttribute('autocomplete', 'off');
    form.down('input[type=text]').setAttribute('autocomplete', 'off');
    form.observe('submit', function(event) {
      event.stop();
      form.down('input[type=text]').focus();
      if (form.newCategoryName.value != '') {
        new Ajax.Request(
                      form.action + '?ajax=1&xpage=plain&' + form.serialize(),
                    {
            onCreate : function () {
              // ignore "cascade" clicks
              form.disable();
              form.notification = new XWiki.widgets.Notification("Adding category...", "inprogress");
            },
            onSuccess : function (response) {
              /* var reference = form._x_item.up('.blog-category-level');
              if (reference) {
                reference.nextSiblings().each(Element.remove);
                reference.insert({after : response.responseText});
                this.initialize();
              }*/
              $$(".blog-categories-list").first().replace(response.responseText);
              this.initialize();
              form.reset();
            }.bind(this),
            onFailure : function (response) {
              new XWiki.widgets.Notification(response.responseText || "Server not responding", "error");
            },
            onComplete : function () {
              form.enable();
              form.notification.hide();
            },
            on401 : function(response) {
              new XWiki.widgets.Notification("You have been logged out, please refresh and log in", "error");
            },
            on403 : function(response) {
              new XWiki.widgets.Notification("You are not allowed to create the target page", "error");
            },
            on409 : function(response) {
              new XWiki.widgets.Notification("Target page already exists, please choose a different name", "error");
            },
            // 0 is returned for network failures, except on IE where a strange large number (12031) is returned.
            on0 : function(response) {
              response.request.options.onFailure(response);
            }
          }
        );
      }
    }.bindAsEventListener(this));
    form.down('a').observe('click', function(event) {
      this.reset();
      event.stop();
    }.bindAsEventListener(form));
    form.observe('reset', function() {
      form.hide();
    });
  },
  /**
   * Ajax category deletion.
   * For all delete buttons, listen to "click", and make ajax request to remove the category. Remove the corresponding
   * HTML element on success (replace it with a small notification message). Display error message (alert) on failure.
   */
  addDeleteListener : function() {
    $$(".blog-category-level").each(function(item) {
      // Prototype bug in Opera: $$(".blog-category-level a.delete") returns only the first result.
      // Quick fix until Prototype 1.6.1 is integrated.
      item = item.down('a.delete');
      if (!item) {
        return;
      }
      item.observe('click', function(event) {
        item.blur();
        event.stop();
        if (item.disabled) {
          // Do nothing if the button was already clicked and it's waiting for a response from the server.
          return;
        } else {
          new XWiki.widgets.ConfirmedAjaxRequest(
            /* Ajax request URL */
            item.href + "&display=list&xpage=plain&ajax=1",
            /* Ajax request parameters */
            {
              onCreate : function() {
                // Disable the button, to avoid a cascade of clicks from impatient users
                item.disabled = true;
              },
              onSuccess : function(response) {
                // Reload the category tree, since the subcategories of the deleted one must go up one level.
                $$(".blog-categories-list").first().replace(response.responseText);
                this.initialize();
              }.bind(this),
              onComplete : function() {
                // In the end: re-enable the button
                item.disabled = false;
              }
            },
            /* Interaction parameters */
            {
               confirmationText: "Are you sure you want to delete this category? This action is not reversible.",
               progressMessageText : "Deleting category...",
               successMessageText : "Deleted",
               failureMessageText : "Failed to delete category"
            }
          );
        }
      }.bindAsEventListener(this));
    }.bind(this));
  }
});
// ======================================
document.observe('xwiki:dom:loaded', function() {
  new XWiki.blog.Categories();
  $$(".blog-categories-list.subcategories").each(function(item) {
    var toggler = new Element("a", {style : "display: block; cursor: pointer; float: right; font-style: italic;"}).update("show »");
    var list = item.down("div", 1);
    toggler.observe("click", function() {
      list.toggle();
      toggler.update(list.visible() ? "« hide" : "show »");
    });
    item.down("strong").insert({after : toggler});
    item.down("strong").insert({after : "&nbsp;&nbsp;"});
    list.toggle();
  });
});
