(function($) {
  /*
   * Übersetzung
   */
  $.setupLocalization = function(update_bindings) {
    Server.lang  = $(document).getUrlParam("lang") || Server.lang;
    $("[rel=set_language]").removeClass("active");
    $("[rel=set_language][lang="+Server.lang+"]").addClass("active");

    // Events
    $("[rel=set_language]").live("click", function() {
      $("[rel=set_language]").removeClass("active");
      $(this).addClass("active");
      Server.lang = $(this).attr("lang");
      $.updateLocalization();
      $(document.body).trigger("updateLocalization");
      return false;
    });

    $.updateLocalization();

    if (update_bindings === undefined) return;
    $(document).bind(update_bindings, function() {
      $.updateLocalization();
    });
  }

  $.updateLocalization = function(callback) {
    $("[lang*=de-]").localize("application", {
      language: Server.lang,
      pathPrefix: "lang",
      skipLanguage: "de",
      callback: callback || function(){}
    });
    $("[lang*=brand-]").localize("brand", {language: Server.lang, pathPrefix: "lang"});
  }

  $.localizedKeys = function(hash) {
    var localizedHash = {};
    $.each(hash, function(k, v) {
      var keyTranslation = k.t(k.toLowerCase().replace(/ /, '_').toString());
      localizedHash[keyTranslation] = v;
    });
    return localizedHash;
  }
  
  $.fn.getLocalization = function() {
    var root = ($(this).parent().length > 0) ? $(this).parent() : $(this);
    root.find("[lang*=de-]").localize("application", { language: Server.lang, pathPrefix: "lang", skipLanguage: "de" });
  }

  String.prototype.t = function(key) {
    for (pkg in $.localize.data[Server.lang]) {
      var data = $.localize.data[Server.lang][pkg];
      if (data[key] != undefined) return data[key];
    }
    return this.toString();
  }


  /*
   * Location Hash
   */
  $.locationHash = function(param) {
    var h = window.location.hash;
    if (h && h.length > 0) {
      // TODO: bei Hash #profil/adressbuch direkt das Adressbuch aktivieren, etc.
      var params = h.substr(1, h.length).split("/");
      if (param == undefined) {
        return params;
      } else {
        return (params[param] == undefined) ? false : params[param];
      }
    } else {
      return false;
    }
  }

  /*
   * Toggle Text
   */
  $.fn.toggleText = function(a, b) {
    return this.each(function() {
      jQuery(this).text(jQuery(this).text() == a ? b : a);
    });
  };


  /*
   * Fill-in Forms
   */
  $.fn.fillIn = function(data) {
    var form = $(this);
    $.each(data, function(key, value) {
      var el = $(form).find("[name="+key+"]");
      if (el.is("select")) {
        el.find("option[value="+value+"]").attr("selected", "selected");
      } else if (el.is("input") && el.attr("type") == "radio") {
        $.each(el, function(i, radio) {
          if ($(radio).attr("value") == value) $(radio).attr("checked", "checked");
        });
      } else {
        el.val(value);
      }
    });
  };

  /*
   * Highlight Effect
   */
  $.fn.highlightFade = function(opts) {
      opts = $.extend({from:"#ffefae",to:"#ffffff",speed:1200}, opts || {});
      $(this)
	  .css({backgroundColor: opts['from']})
	  .animate({backgroundColor: opts['to']}, opts['speed'], function() {
	      $(this).css({backgroundColor: ""});
	  });
  };

  /*
   * Loader
   */
  $.loaderQueue = 0,
  $.showLoader = function() {
    $.loaderQueue += 1;
    if ($("#application_loader").length == 0) {
      $("body").append('<div id="application_loader"><div /></div>');
    }
    $("#application_loader").show();
  },

  $.hideLoader = function(force) {
    $.loaderQueue -= 1;
    if (force) $.loaderQueue = 0;
    if ($.loaderQueue <= 0) {
      $("#application_loader").hide();
    }
  },
  $("#application_loader").live("click", function() {$.hideLoader()});


  /*
   * Ajax Upload
   */

   $.fn.ajaxUpload = function(onSubmit, onComplete, onChange) {
     onChange = onChange || function(f,e) {this.submit()};
     Server.uploadFile($(this).attr("id"), onSubmit, onComplete, onChange);
   }
   
   $.fn.addToForm = function(options) {
     var form = $(this);
     $.each(options, function(key, value) {
       form.append('<input type="hidden" name="'+key+'" value="'+value+'" />');
     });
   }

  /*
   * Dimensions
   */
  $.fn.trueHeight = function() {
    return this.height() + this.xouterHeight();
  }

  $.xparseInt = function(val) {
    var value = (val == "auto") ? 0 : parseInt(val);
    if (isNaN(value)) value = 0;
    return value;
  }

  $.fn.xouterHeight = function() {
    return $.xparseInt(this.css("margin-top"))
    + $.xparseInt(this.css("margin-bottom"))
    + $.xparseInt(this.css("padding-top"))
    + $.xparseInt(this.css("padding-bottom"))
    + $.xparseInt(this.css("border-top-width"))
    + $.xparseInt(this.css("border-bottom-width"));
  }

  $.fn.trueWidth = function() {
    return this.width() + this.xouterWidth();
  }

  $.fn.xouterWidth = function() {
    return $.xparseInt(this.css("margin-left"))
    + $.xparseInt(this.css("margin-right"))
    + $.xparseInt(this.css("padding-left"))
    + $.xparseInt(this.css("padding-right"))
    + $.xparseInt(this.css("border-left-width"))
    + $.xparseInt(this.css("border-right-width"));
  }


  /*
   * Toggle class
   */
   $.fn.smallWidth = function(width, minClass) {
     var el = this;
     function fit() {
       $(el).toggleClass(minClass, $(window).width() < width);
     }
     $(document).bind("ready", fit);
     $(window).bind("resize", fit);
   }

  /*
   * Fit Application To Window
   */
   $.fn.fitToWindow = function() {
     // Private Functions
     function resize(e) {
       // Don't resize hidden elements
       if ($(e.data.frame).is(":hidden")) return;

       var frameHeight = e.data.mount.height();
       e.data.frame.children(".vertical-fixed").each(function() {
         frameHeight -= $(this).trueHeight();
       });

       // Must be exactly one element at the moment
       e.data.frame.children(".vertical-elastic").each(function() {
         frameHeight -= $(this).xouterHeight();
         $(this).css("height", frameHeight);
         $(this).find(".col").css("height", frameHeight);
       });

       $(".vertical-fill").each(function() {
         var height = $(this).closest(".vertical-elastic, .vertical-fixed").height();
         $(this).siblings(".vertical-pad").each(function() {
           height -= $(this).trueHeight();
         });
         //alert(height);
         $(this).css("height", height - $(this).xouterHeight());
       });


     }

     // Provides the boundaries
     var mount = $(this).closest(".vertical-elastic");
     if (mount.length == 0) mount = $(window);

     // Contains the elements
     var frame = $(this);

     // Bindings
     $(this).bind("resize", {mount: mount, frame: frame}, resize);
     $(document).bind("ready app.resize", {mount: mount, frame: frame}, resize);
     $(window).bind("resize", {mount: mount, frame: frame}, resize);
   }


  /*
   * Same Height Columns
   */
  $.fn.sameHeight = function() {
    var maxHeight = 0; var maxCol; var cols = [];
    this.each(function() {
      $(this).css("height", "");
      if ($(this).height() > maxHeight) {
        if (maxCol != undefined) cols.push(maxCol);
        maxCol = this;
        maxHeight = $(this).height();
      } else {
        cols.push(this);
      }
    });

    $.each(cols, function() {
      $(this).height($(maxCol).height());
    });
   }

  /*
   * Does an object contain any keys?
   */
  $.isEmpty = function(obj) {
    var counter = 0;
    $.each(obj, function(k, v) {counter++});
    return (counter == 0) ? true : false;
  }

  /*
   * (Ohne Worte ...)
   */
  $.isIE = function() {
    var ie/*@cc_on = true@*/;
    return ie ? true : false;
  }
})(jQuery);
