/**
 * Class WidgetLoader
 *
 * Hjelpeklasse for å initialisere ulike typer widgets på en hurtig og effektiv
 * måte.
 *
 */
function WidgetLoader() {

    var mc = this;

    /**
     * 
     */
    var requestedQue = [];

    /**
     *
     */
    var loadingInProgress = false;

    /**
     * Inneholder predefinerte widgets
     */
    var templates = [];

    /**
     * Register for lastedede scripts
     */
    var loadedScripts = [];

    /**
     * Inneholder de widgetene som er initialisert, altså instanser av en type widget
     */
    var activeWidgets = []

    /**
     * Laster inn det som trengs til en widget
     */
    function _load( name, showParams, method ) {

        var template = templates[name];

        //
        // Sjekker om vi har en template for forespurt widget
        if( typeof template != 'object' ) {
            feedbackHelper.showError("Ingen widget-template satt for '"+ name +"'" );
            return ;
        }

        var widgetType = template.type;
        var widgetParams = template.params;

        //
        // Sjekker at vi minimum har widget-typen
        if( widgetType == null || widgetType == "" || typeof widgetType == 'undefined' ) {
            feedbackHelper.showError("Ingen widget-type gitt for '"+ name +"'" );
            return ;
        }

        if( typeof widgetParams != 'object') {
            widgetParams = {};
        }
        if( typeof showParams != 'object') {
            showParams = {};
        }

        //
        // widgetParams har prioritet over showParams
        var options = widgetParams; //$.extend(showParams, widgetParams);
        options.type = template['type'];

        //
        // Sjekker om typen allerede er lastet (-1 = finnes ikke)
        if( jQuery.inArray(widgetType, loadedScripts) == -1 ) {
//            feedbackHelper.showNotice("Laster type '"+ widgetType +"'" );

            //
            //
            $.ajax({
                url:        '/widget/async-load-script/',
                dataType:   'html',
                type:       'post',
                data:       options,
                success: function( htmlResponse ) {
                    //
                    // Laster inn html-script-resonsen inn i DOM
                    $("body").append(htmlResponse);
                    
                    //
                    // Registerer at vi har lastet nødvendig html-kilde for aktuelt navn
                    loadedScripts.push( widgetType );

                    //
                    // Så laster vi inn selve html-strukturen for aktuell widget
                    _loadWidgetSource( name, showParams, method );
                },
                error: function() {
                    feedbackHelper.showError("Det har oppstått en ikke-brukerfeil");
                }
            });

            //
            // Jmf. naturen til asynkrone kan vi ikke være sikre på at aktuelle
            // scripts er lastet før success-callbacket er kallt i ajax-kallet over
            // Der aktiverers netste skritt.
            //
            return ;
        }

        //
        // Sjekker om widgetKilden allerede er lastet (-1 = finnes ikke)
        if( typeof activeWidgets[name] != 'object' ) {
            _loadWidgetSource( name, showParams );

            //
            // Jmf. asyn-natur 
            return ;
        }

        //
        // Vi har alt vi trenger for å kjøre show-metoden direkte!
        _show( name, showParams, false, method );
        
        // callbackFunction(name, showParams, false);
    }



    function _loadWidgetSource( name, showParams, method ) {

//        feedbackHelper.showNotice("Laster widget-kilde '"+ name +"'" );

        var template = templates[name];
        var widgetParams = template.params;
        var widgetType = template.type;

        if( typeof widgetParams != 'object') {
            widgetParams = {};
        }
        if( typeof showParams != 'object') {
            showParams = {};
        }

        //
        // widgetParams har prioritet over showParams
        var options = widgetParams;//$.extend(showParams, widgetParams);
        options.type = template['type'];
        options.name = name;
        
        //
        //
        $.ajax({
            url:        '/widget/async-load-source/',
            dataType:   'html',
            type:       'post',
            data:       options,
            success: function( htmlResponse ) {
                
                //
                // Laster inn html-resonsen inn i DOM
                $("body").prepend(htmlResponse);
                
                //
                //
                var widgetElement = $("#" + name);

                //
                // Initialiserer widgeten
                eval( "widgetElement." + widgetType + "(widgetParams);" );

                if( typeof widgetParams.zindex == "number" ) {
                    $(widgetElement).css("z-index", widgetParams.zindex);
                    $(widgetElement).prev().css("z-index", (widgetParams.zindex-10));
                }

                //
                // Registerer at vi har lastet nødvendig script for aktuell type
                activeWidgets[name] = widgetElement;

                //
                // Så laster vi inn selve html-strukturen for aktuell widget
                _show( name, showParams, false, method );

                // callbackFunction(name, showParams, false);
            },
            error: function() {
                feedbackHelper.showError("Det har oppstått en ikke-brukerfeil");
            }
        });
    }

    /**
     *
     */
    function _show(name, params, direct, method ) {

        var widgetType = templates[name].type;

        //
        // jQuery sin syntaks for funksjonskall på widgeter er $(element).widgetName("funksjon", params);
        // må vi bruke eval 
        eval("activeWidgets[name]."+widgetType+"('"+ method +"', params)");

        if( direct ) {
            return ;
        }

        //
        // Vi er ferdig med en runde
        loadingInProgress = false;

        //
        // Ok
        _run();
    }

    /**
     * Starter lastingen av køen
     */
    function _run () {
        
        if( loadingInProgress ) {
            return;
        }

        //
        // Henter ut det første elementet
        var next = requestedQue.shift();
        
        if( typeof next == 'object') {
//            alert("KJØRER EN RUNDE");
            loadingInProgress = true;
            _load(next.name, next.params, next.method);
        }
    }


    /**
     * Registrerer såkalte templater for senere bruk.
     *
     * Denne funksjonen er sentral i lazy-init-prinsippet der ressursene ikke
     * blir lastet før de faktisk brukes
     */
    this.addTemplate = function( name, type, params ) {

//        var options = $.extend({
//            type:   type,
//        }, params);

        templates[name] = {
            type: type,
            params: params
        };
    }

    /**
     * Aktiverer show-funksjonen til widgeten med gitt navn
     */
    this.show = function ( name, params ) {

        //
        // Sjekker om vi allerede har initialisert forespurt widget
        if( typeof activeWidgets[name] != 'object' ) {

            requestedQue.push( {name: name, params: params, method: 'show'} );
            
            //
            // Aktiverer initialisering
            _run();

            //
            // Prøver å laste widget, load-funksjonen
            // _load(name, params, true);
            return ;
        }
        //
        // Vi har det vi trenger å for å kjøre direkte
        _show(name, params, true, 'show');
    }


    /**
     * Aktiverer villkårlig funksjon til widgeten med gitt navn
     */
    this.call = function ( name, method, params ) {

        //
        // Sjekker om vi allerede har initialisert forespurt widget
        if( typeof activeWidgets[name] != 'object' ) {

            requestedQue.push( {name: name, params: params, method: method} );

            //
            // Aktiverer initialisering
            _run();

            //
            // Prøver å laste widget, load-funksjonen
            // _load(name, params, true);
            return ;
        }
        //
        // Vi har det vi trenger å for å kjøre direkte
        _show(name, params, true, method);
    }

    /**
     * Returnerer hvorvidt en widget er aktivert eller ikke
     */
    this.isActive = function( name ) {
        return ( typeof activeWidgets[name] == 'object' );
    }
}
