$(function() {
   (function() {
      var currentLocation = $.data(window, "location");
      if (!currentLocation || location.href !== currentLocation) {
         restoreDisplay();
         updateColumns();
         enableEditors();
         enableControls();
         //Hyphenator.run();
         $.data(window, "location", location.href);
      }
      setTimeout(arguments.callee, 500);
   })();
   enableGrids();
   enableCancel();
   enableMailto();
   enableControls();
   return;
});

$.extend($.expr[':'], {
    "containsIgnoreCase": "jQuery.fn.text.apply([a]).toLowerCase().indexOf(m[3].toLowerCase())>=0"
});

$.fn.extend({
   // Adapted from http://trac.edgewall.org/chrome/common/js/wikitoolbar.js
   selection: function selection(prefix, suffix) {
      var start, end, sel, scrollPos, subst, element = this.get(0);
      this.focus();
      
      if (typeof prefix === "undefined" && typeof suffix === "undefined") {
         if (document.selection !== undefined) {
            sel = document.selection.createRange().text;
         } else if (element.setSelectionRange !== undefined) {
            start = element.selectionStart;
            end = element.selectionEnd;
            scrollTop = element.scrollTop;
            sel = this.val().slice(start, end);
            $.data(this, "selection", {
               start: start,
               end: end,
               scrollTop: scrollTop
            });
         }
         return sel;
      }

      sel = this.selection();
      if (sel.match(/ $/)) { // exclude ending space char, if any
         sel = sel.slice(0, -1);
         suffix = suffix + " ";
      }

      subst = arguments.length > 1 ? prefix + sel + suffix : prefix;
      if (document.selection !== undefined) {
         document.selection.createRange().text = subst;
         element.caretPos -= suffix.length;
      } else if (element.setSelectionRange !== undefined) {
         var data = $.data(this, "selection");
         this.val(this.val().slice(0, data.start) + subst +
               this.val().slice(data.end));
         var pos = data.start + (sel ? subst.length : prefix.length);
         element.setSelectionRange(pos, pos);
         element.scrollTop = data.scrollTop;
      }
   },

   editable: function() {
      $(this).each(function() {
         var self = $(this);
         var input = $('<textarea rows="5" cols="40"></textarea>');
         var content = $('<div class="content" />').html(self.html());
         var controls = $('<div class="controls"><button>bearbeiten</button>' +
               '<span class="status">speichern...</span>' + 
               '<a href="">abbrechen</a></div>');
   
         self.html(content);
         self.append(controls);
         
         var controls = self.find(".controls");
         var status = self.find(".status").hide();
   
         var cancel = controls.find("a").click(function() {
            toggle.text($.data(self, "toggle"));
            self.find(".content").html($.data(self, "content"));
            $.data(self, "editable", false);
            $(this).hide();
            return false;
         }).hide();
         
         var toggle = controls.find("button").click(function() {
            var content = self.find(".content");
            var cssId = self.attr("id");
            var type = cssId.split(":").pop();
            // FIXME: Ugly hack to unify the API id property
            var id = cssId.replace(new RegExp("([^:]*)$"), "edit");
            var editable = !!$.data(self, "editable");
            if (editable) {
               status.show();
               var data = api({
                  id: id, 
                  type: type, 
                  value: $.trim(input.val())
               });
               $(this).text($.data(self, "toggle"));
               content.html(data);
               status.hide();
               cancel.hide();
            } else {
               $.data(self, "toggle", $(this).text());
               $.data(self, "content", content.html());
               $(this).text("speichern");
               var data = api({id: id, type: type});
               input.width(content.width() - 2);
               input.height(Math.max(content.height() - 3, 100));
               // FIXME: Remove ugly check if data is a jQuery object
               content.html(data.html ? data : input.html(data));
               cancel.show();
            }
            $.data(self, "editable", !editable);
            return false;
         }).css("margin-right", 10);;
      });
   },

   rheonify: function() {
      var self = this;
      var input = self.find("textarea");

      var preview = function preview(mode) {
         if (mode === "off") {
            self.find("#preview").hide();
            input.show();
            return;
         }
         var result = api({
            id: self.find("input[name=id]").val(),
            source: encodeURIComponent(input.val())
         });
         input.hide().after(self.find("#preview"));
         self.find("#preview").html(result).width(input.width())
               .height(input.height()).show().click(function() {return false});
      }
      preview("off");
      
      self.find("#toggle").toggle(function() {
         preview("on");
         $.data(this, "text", $(this).text());
         $(this).text("bearbeiten");
         return false;
      }, function() {
         preview("off");
         $(this).text($.data(this, "text"));
         return false;
      })
   
      self.find(".buttons a").click(function() {
         var name = $(this).text();
         switch (name) {
            case "em":
            input.selection("_", "_");
            break;
   
            case "strong":
            input.selection("*", "*");
            break;
            
            case "hr":
            input.selection("\n---\n", "\n");
            break;
   
            case "link":
            var url = prompt("Wie lautet die Adresse für den Hyperlink?", "http://");
            if (url = encodeURI($.trim(url))) {
               var text = input.selection();
               if (text) {
                  input.selection("(" + url + " ", ")");
               } else if ((text = $.trim(prompt("Wie lautet der Text für den Hyperlink?", "")))) {
                  input.selection("(" + url + " " + text + ")", "");
               }
            }
            break;
            
            default:
            input.selection(name + ": " + input.selection());
            break;
          }
         return false;
      });
   },

   formify: function() {
      var self = this;
      $(this).find("dd:not(.escape)").each(function(item) {
         var name = $(this).attr("class");
         var type = (name.indexOf("password") === 0 ? "password" : "text");
         var input = $('<input type="' + type + '" />');
         input.attr({name: name, size: 40});
         $(this).html(input.val($(this).text()));
      });
      $(this).find("input").focus(function() {
         $(this).addClass("enabled");
         //$(this).parent().prev("dt").addClass("enabled");
      }).blur(function() {
         $(this).removeClass("enabled");
         $(this).parent().prev("dt").removeClass("enabled");
      });
  }
});

var api = function api(param) {
   var result = null;
   if (param) {
      $.ajax({
         async: false,
         type: "POST",
         url: coplaner.api,
         data: param,
         success: function success(data, status) {
            result = data;
         },
         error: function error(xhr, status, ex) {
            $("#title h1").html("Zugriff verweigert");
            result = $('<div class="paragraph">Du hast keine ausreichende Berechtigung für diese Aktion.</div>');
         }
      });
   }
   return result;
}

var getName = function getName(link) {
   var name = prompt("Bitte gib einen Namen ein:", "");
   if (name) {
      link.attr("href", link.attr("href") + "=" + encodeURIComponent(name));
      return true;
   }
   return false;   
}

var remove = function remove(constructor, ids) {
   if (ids && ids.length > 0) {
      if (confirm("Sollen " + ids.length + " Objekte gelöscht werden?")) {
         return api([constructor, ids, "remove"],join(":"));
      }
   }
   return false;
}

var restoreDisplay = function restoreDisplay() {
   // Restore display from hash
   if (location.hash && location.hash.indexOf(":") > -1) {
      var param = {id: location.hash.substr(1)};
      var html = api(param);
      $(".yui-u.first").html(html);
      $("div.grid tbody tr[id=_" + param.id + "]").addClass("selected");
   }
   return;
}

var sort = function(list) {
   var items = list.children("li").get();
   items.sort(function(a, b) {
      var v1 = $(a).text().toLowerCase();
      var v2 = $(b).text().toLowerCase();
      return (v1 < v2) ? -1 : (v1 > v2) ? 1 : 0;
   });
   $.each(items, function(index, item) {
      list.append(item);
   });
}

var enableCancel = function enableCancel() {
   $("a.cancel").click(function() {
      history.back();
      return false;
   });
   return;
}

var enableEditors = function enableEditors() {
   $("form.propertyEditor").formify();
   if ($.inArray(coplaner.status, ["moderator", "admin"]) > -1) {
      $("div.editable").editable();
      return;
   }
   return;
}

var enableGrids = function enableGrids() {
   var translate = function translate(str) {
      var specials = ['ä','ö','ü','ß'];
      var replacements = ['a','o','u','s'];
      var re = new RegExp(specials.join("|"), "g");
      return str.toLowerCase().replace(re, function(match) {
         return replacements[$.inArray(match, specials)];
      });
   }

   var sort = function(grid, direction, selector) {
      var list = [];

      $(grid).find("tbody tr").each(function() {
         list.push($(this).clone(true));
      });

      list.sort(function(a, b) {
         var aVal = $(a).find(selector).text();
         var bVal = $(b).find(selector).text();
         var result = aVal - bVal;
         if (!result) {
            var aStr = translate(aVal);
            var bStr = translate(bVal);
            if (aStr > bStr) {
               result = 1 
            } else if (aStr < bStr) {
               result = -1;
            } else {
               result = 0;
            }
         }
         return result * direction;
      });

      $(grid).find("tbody tr").each(function(index) {
         $(this).replaceWith($(list[index]));
      });
   }

   $(".grid-header a").each(function() {
      $(this).click(function() {
         switch ($(this).attr("class")) {
            case "add":
            var type = $(this).parents("ul").attr("id");
            $(this).attr("href", $(this).attr("href") + 
                  "?action=add&type=" + type + "&name");
            return getName($(this));

            case "delete":
            var selection = $.data($(this).parents("ul")
                  .next("div.grid").get(0), "selection");
            if (selection && confirm("Bist Du ganz sicher?")) {
               var id = selection[0];
               id = id.split(":");
               id[2] = "delete";
               var msg = api({id: id.join(":")});
               if (msg) {
                  $(".yui-u.first").html(msg);
               } else {
                  location.reload();
               }
               return false;
            }
            return false;
            
            default:
            return true;
         }
      });
   });

   $("div.grid").each(function(index) {
      var self = this, status = "expanded";
      
      var collapse = function() {
         $(self).find("tbody tr:gt(4)").hide();
      }
      
      var expand = function() {
         $(self).find("tbody tr").show();
      }

      var rows = $(this).find("tbody tr").click(function(event) {
         var currentSelection = $.data(self, "selection") || [];
         var id = $(this).attr("id").substr(1); // Remove leading character
         if (event.metaKey) {
            var index = $.inArray(id, currentSelection);
            if (index < 0) {
               $(this).addClass("selected");
               currentSelection.push(id);
            } else {
               $(this).removeClass("selected");
               currentSelection.splice(index, 1);
            }
         } else {
            currentSelection = [id];
            document.location.hash = id;
            $(self).find("tbody tr[class=selected]").removeClass("selected");
            $(this).addClass("selected");
         }
         $.data(self, "selection", currentSelection);
      });
      
      if (!$(this).prev(".grid-header").hasClass("expand") && rows.length > 5) {
         $(this).prev(".grid-header").append($("<li />")
               .html($('<a href="" />').toggle(function() {
            collapse();
            status = "collapsed";
            $(this).text("max");
            return false;
         }, function() {
            expand();
            status = "expanded";
            $(this).text("min");
            return false;
         }).click()));
      }
      
      var direction = 1;
      $(this).find("th").click(function() {
         var selector = "td." + $(this).attr("class");
         // Expand grid when sorting
         $(this).parents(".grid").prev(".grid-header").find("a:contains(max)").click();
         direction *= -1;
         sort(self, direction, selector);
      });
      
      // Default sort
      var th = $(this).find("th:first");
      var header = th.parents(".grid").prev(".grid-header");
      var toggle = header.find("a:contains(max)");
      sort(self, header.hasClass("desc") ? -1 : 1, "td." + th.attr("class"));
      toggle.click().click();
   });
}

var enableMailto = function enableMailto() {
   $("#mailto").click(function() {
      var ids = [];
      $("tr.selected").each(function() {
         var id = $(this).attr("id").substr(1).split(":");
         id.pop();
         id.push("mailto");
         ids.push(id.join(":"));
      });
      if (ids.length < 1) {
         alert("Bitte wähle zuerst mindestens einen Teilnehmer oder eine Gruppe aus.");
         return false;
      }
      var result = api({id: ids});
      if (!result) {
         alert("Mangels Adressen ist eine Benachrichtigung leider nicht möglich.");
         return false;
      }
      $(this).attr("href", "mailto:?" + result + 
            "&subject=[coplaner] " + $.trim($(this).text()));
      return true;
   });
}

var enableControls = function enableControls() {
   $("a:contains(drucken)").hide();
   return;
}

var updateColumns = function updateColumns() {
   if (location.hash && location.hash.indexOf(":") > -1) {
      var left = $(".yui-u.first").find(".move-left");
      $("#link-list").html(left.html() || "");
      left.remove();
      //var right = $(".yui-u.first").find(".move-right");
      //$(".yui-u.second").html(right.html() || "");
      //right.remove();
   }
   return;
}

