/* 
    Document   : application.js
    Created on : Sep 5, 2011, 2:27:48 PM
    Author     : Elwin Andriol <elwin@heuveltop.nl>
    Description:
        Application framework JS.
*/

function Application() {
    this.components = [];
    this.componentUpdateTimer = null;
    this.config = false;
    this.loading = false;
    this.role = "guest";
    
    this.addJavaScript = function( src ) {
        var headID = document.getElementsByTagName( 'head' )[0];         
        var script = document.createElement( 'script' );
        script.type = 'text/javascript';
        script.src = src;
        headID.appendChild( script );
    }
    
    this.addStyleSheet = function( href ) {
        var headID = document.getElementsByTagName( 'head' )[0];
        var css = document.createElement( 'link' );
        css.type = 'text/css';
        css.rel = 'stylesheet';
        css.href = href;
        headID.appendChild( css );
    }
    
    this.bufferedResize = function() {
        if ( this.resizeTimer ) {
            clearTimeout( this.resizeTimer );
        }

        this.resizeTimer = setTimeout( 'application.resize();', 250 );
    }
    
    this.componentsUpdate = function() {
        if( this.loading ) {
            for( var i in this.loading ) {
                var component = this.loading[ i ];
                var classname = "Application_Component_" + this.ucfirst( component );
                var ready = {'css': true, 'js': false, 'html': false};
                
                for( var j in document.styleSheets ) {
                    if( document.styleSheets[ j ].href ) {
                        if( document.styleSheets[ j ].href.replace( document.baseURI, '' ) == "css/component/" + component + ".css" ) {
                            try {
                                if( document.styleSheets[ j ].cssRules.length > 0 ) {
                                    ready.css = true;
                                }
                            } catch( e ) {}
                        }
                    }
                }
                
                if( eval( "typeof( " + classname + " );" ) == 'function' ) {
                    ready.js = true;
                }
                
                if( $( "#component-" + component ).length ) {
                    ready.html = true;
                }
                
                if( ready.css && ready.js && ready.html ) {
                    if( typeof( application[ component ] ) != 'object' ) {
                        eval( "application." + component + " = new " + classname + "( application );" );
                        application[ component ].init( this.config.components[ component ] );
                    }

                    if( application[ component ].ready ) {
                        this.loading.splice( i, 1 );
                        this.components.push( component );
                        break;
                    }
                }
            }
        }
        
        if( this.loading.length == 0 ) {
            this.loading = false;
            this.bufferedResize();
            this.splashScreen( false );
        } else {
            this.componentUpdateTimer = setTimeout( 'application.componentsUpdate();', 100 );
        }
    }
    
    this.getDocumentHeight = function() {
        var d = document;
        
        var h = Math.max(
            Math.max( d.body.scrollHeight, d.documentElement.scrollHeight ),
            Math.max( d.body.offsetHeight, d.documentElement.offsetHeight ),
            Math.max( d.body.clientHeight, d.documentElement.clientHeight )
        );
        
        if( $.browser.msie )
            h -= 5;
        
        return h;
    }
    
    this.getDocumentWidth = function() {
        var d = document;
        
        var w = Math.max(
            Math.max( d.body.scrollWidth, d.documentElement.scrollWidth ),
            Math.max( d.body.offsetWidth, d.documentElement.offsetWidth ),
            Math.max( d.body.clientWidth, d.documentElement.clientWidth )
        );
        
        if( $.browser.msie )
            w -= 5;
        
        return w;
    }
    
    this.init = function( config ) {
        this.config = config;
        
        this.splashScreen( true );
        
        if( config.role )
            this.role = config.role;
        
        if( config.preload ) {
            for( var i in config.preload ) {
                this.preload( config.preload[ i ] );
            }
        }
        
        if( config.components ) {
            for( var name in config.components ) {
                this.loadComponent( name );
            }
        }
        
        $( window ).bind( 'resize', this.bufferedResize );
    }
    
    this.loadComponent = function( component ) {
        if( ! this.loading ) {
            this.loading = [];
        }
        
        this.loading.push( component );
        clearTimeout( this.componentUpdateTimer );
        
        $.get(
            "/component/" + component,
            function( data ) {
                var result = jQuery.parseJSON( data );
                
                if( result.status == 'ok' ) {
                    $( '<div>' )
                        .attr( {
                            'class': "component",
                            'id': "component-" + component
                        } )
                        .html( result.html )
                        .hide()
                        .appendTo( 'body' );
                } else {
                    if( typeof( application.error ) == 'object' ) {
                        application.error.show( result.error );
                    } else {
                        alert( result.error );
                    }
                }
            }
        );
        
        this.addStyleSheet( "/css/component/" + component + ".css" );
        this.addJavaScript( "/js/component/" + component + ".js" );
        this.componentUpdateTimer = setTimeout( 'application.componentsUpdate();', 100 );
    }
    
    this.preload = function( image ) {
        if( ! $( '#preload' ).length ) {
            $( '<div>' )
                .attr( 'id', 'preload' )
                .hide()
                .appendTo( 'body' );
        }
        
        $( '<img>' )
            .attr( 'src', image )
            .appendTo( '#preload' );
    }
    
    this.resize = function() {
        var redraw = [];
        var component;
        
        for( i in this.components ) {
            component = this.components[ i ];
            
            if( typeof( application[ component ].reposition ) == 'function' ) {
                if( $( application[ component ].ref ).is( ":visible" ) ) {
                    redraw.push( application[ component ] );
                    application[ component ].hide();
                }
            }
        }
        
        for( i in this.components ) {
            component = this.components[ i ];
            
            if( typeof( application[ component ].reposition ) == 'function' ) {
                application[ component ].reposition();
            }
        }
        
        for( i in redraw ) {
            redraw[ i ].show();
        }
    }
    
    this.splashScreen = function ( show ) {
        if( $( '#splashscreen' ).length ) {
            $( '#splashscreen' ).remove();
        }
        
        if( show ) {
            $( '<div>' )
                .attr( 'id', 'splashscreen' )
                .css( 'z-index', 9999 )
                .appendTo( 'body' );
            $( '<div>' )
                .attr( 'class', 'frame' )
                .appendTo( '#splashscreen' );
            $( '<img>' )
                .attr( 'src', '/img/init.gif' )
                .appendTo( '#splashscreen .frame' );
            $( '<div>' )
                .attr( 'class', 'message' )
                .html( this.config.message )
                .appendTo( '#splashscreen' );
                
        }
    }
    
    this.ucfirst = function( str ) {
        str += '';
        var f = str.charAt( 0 ).toUpperCase();
        return f + str.substr( 1 );
    }
}

function var_dump( obj ) {
    var out = '';
    for( var i in obj ) {
        out += i + ": " + obj[ i ] + "\n";
    }

    alert( out );
}
