function XposUtils(){

    /**
     * UI.Layout-Objekt, wird von initLayout() gesetzt
     */
    var uiLayout = null

    /**
     * Initialisiert ein UI.Layout-Objekt mit den übergebenen oder den default-Optionen und gibt die Instanz zurück.
     * Die default-Optionen erstellen das 'normale' XPOS-Layout (North: Navigation, Center: Karte, East: Aktions-Panel)
     * @param customOptions   optional, falls leer werden die default-Optionen verwendet
     * @return UI.Layout
     */
    function initLayout(customOptions) {

        /**
         * Mischt zwei Sätze von Optionen miteinander; Einträge aus additionalOptions werden baseOptions hinzugefügt oder überschreiben
         * ggf. bereits vorhandene gleichnamige Eigenschaften in baseOptions
         * @param baseOptions
         * @param additionalOptions
         */
        function mergeOptions(baseOptions, additionalOptions){
            for (var prop in additionalOptions){
                if ('object' == typeof additionalOptions[prop] && baseOptions[prop] && 'object' == typeof baseOptions[prop]){
                    mergeOptions(baseOptions[prop], additionalOptions[prop])
                } else {
                    baseOptions[prop] = additionalOptions[prop]
                }
            }
        }

        var defaultOptions = {
            applyDefaultStyles: false,
            center: {
                resizable: false
            },
            north: {
                resizable: false,
                size: 44,
                spacing_open: 0
            },
            east: {
                resizable: true,
                size: 300
            },
            south: {
                size: 50,
                spacing_open: 2
            }

        }

        if (customOptions) mergeOptions(defaultOptions, customOptions)

        uiLayout = $('body').layout(defaultOptions);
    }

    /**
     * Versieht die Links der Hauptnavigation mit hover-Effekten
     */
    function initNavigation() {
        $('a', '#xpos_main_menu').hover(
                function() {
                    $(this).addClass('ui-state-hover')
                },
                function() {
                    $(this).removeClass('ui-state-hover')
                }
         )
    }

    /**
     * Wandelt alle passenden Elemente in der Toolbox in JqueryUI-Buttons um
     */
    function initToolbox(){
        $('button, submit', '#xpos_toolbox_pane').button()
    }

    /**
     * jQuerifiziert alle <select>-Elemente
     */
    function initSelectmenus(){
        $('select[class!="jqui_ignore"]').selectmenu()
    }

    /**
     * Initialisiert das User-Interface (UI.Layout && Hover-Effekte für Hauptnavigation)
     * @param Object    layoutOptions   optional: eigene Einstellungen für die Aufteilung der UI.Layout-Panes, falls leer wird default verwendet
     */
    this.initUI = function(layoutOptions){
        initLayout(layoutOptions)
        initNavigation()
        initToolbox()
        initSelectmenus()
    }

    /**
     * Fügt HTML für eine Nachricht in die Statusleiste ein (aktuelles Datum und Uhrzeit werden vorgestellt)
     * @param msg   String  die Nachricht
     * @param icon  String  optional: ein Icon, dass mit der Nachricht angezeigt werden soll    default: alert
     * @param state String optional: highlight|error  default: highlight
     */
    this.addStatusMsg = function (msg, icon, state){

        function format(number){
            if (number < 10) return '0' + number
            else             return number
        }

        // default-Werte für Status und Icon
        if (!state) state = 'highlight'
        if (!icon) icon = 'info'

        // Datum und Zeit ermitteln und formatieren
        var date = new Date()
        var dateOut = [
                format(date.getDate()),
                format(date.getMonth() + 1),
                date.getFullYear()
        ].join('.')
        var timeOut = [
                format(date.getHours()),
                format(date.getMinutes()),
                format(date.getSeconds())
        ].join(':')

        // Datum und Zeit der Nachricht voranstellen
        msg = dateOut + ' ' + timeOut + ' Uhr: ' + msg

        // UI-formatiertes HTML für Nachricht erstellen
        var out = ['<div class="ui-widget ui-widget-content ui-state-',
                   state,
                   ' xpos_ui_state">']
        if (icon){
            out.push('<div class="ui-icon ui-icon-')
            out.push(icon)
            out.push('"></div>')
        }
        out.push('<div class="ui_msg">' + msg + '</div>')
        out.push('</div>')

        // DOM-Element für Statusnachricht erstellen und dem Inhalt der Statusleiste voranstellen
        var msg = $(out.join(''))
        $('#xpos_statusleiste').prepend(msg)

        //  neues DOM-Element in Blickpunkt scrollen und animieren
        msg[0].scrollIntoView(true)
        msg.effect('pulsate', {}, 300);
    }

    /**
     * Animiert die mit jQuerySelection übergebenen Elemente (sinnvoll z.B. falls Teile der Seite per Ajax aktualisiert wurden).
     * @param jQuerySelection
     */
    this.animateUpdate = function(jQuerySelection){
        jQuerySelection.fadeOut('fast').fadeIn('fast')
    }

    /**
     * Ajax-Aktivitätsanzeige ersetzt den Inhalt der übergebenen jQuery-Selektion durch das Spinner-Element des Dokuments
     * Die Ajax-Anfrage muss sich dann selber darum kümmern den Spinner wieder durch den angeforderten Inhalt zu ersetzen
     * @param jQuerySelection
     */
    this.attachAjaxSpinner = function(jQuerySelection){
        var height = jQuerySelection.height() + 'px'
        var width = jQuerySelection.width() + 'px'
        var spinner =  $('#xpos_ajax_spinner').clone().css('height', height).css('width', width)
        jQuerySelection.empty().append($(spinner).removeClass('xpos_hidden'))
    }

    /**
     * Liefert formatiertes HTML zur Ausgabe für fehlgeschlagene Ajax-Requests. Falls über den zweiten Parameter nicht anders anegeben, wird
     * auch die Statusleiste mit der Fehlermeldung aktualisiert.
     * @param Object    xhr          Objekt zum HTTP-Status der Anfrage (z.B. xhr.status == 500, xhr.statusText = 'Internal Server Error')
     * @param Boolean   ignoreStatus optional: falls true, wird die Statusleiste nicht aktualisiert
     */
    this.getAjaxErrorHtml = function(xhr, ignoreStatus){
        var msg = [
                'Ajax-Anfrage fehlgeschlagen:',
                xhr.status,
                xhr.statusText
        ]
        var html = [
            "<div class='ui-state-error ui-corner-all xpos_ui_state'>",
            '  <div class="ui-icon ui-icon-alert"></div>',
            '    <div class="ui_msg">',
                   msg[0] + '<br>',
                   msg[1] + ' ' + msg[2],
            '  </div>',
            '</div>'
        ]
        if (!ignoreStatus) this.addStatusMsg(msg.join(' '), 'alert', 'error')
        return html.join('\n')
    }

    /**
     * Gibt den Handler für das UI.Layout-Objekt zurück
     */
    this.getLayout = function(){
        return uiLayout
    }
}
