/*!
 * Denbel object
 * @version: 1.0
 * @author: M.F.Endenburg
 * @copyright (c) Denbel Systems, 2007
 * www.denbel.nl
 */

/**
 * Denbel object
 * @var object
 */
var Denbel =
{
	/**
	 * Loads a Denbel namespace
	 * @return object
	 */
	load: function()
	{
	    var a = arguments, o = null, i, j, d;
	    
	    for( i = 0; i < a.length; i++ )
	    {
	        d = a[i].split( '.' );
	        o = Denbel;
	
	        // Denbel is implied, so it is ignored if it is included
	        for( j = ( d[0] == 'Denbel' ) ? 1 : 0; j < d.length; j++ )
	        {
	            o[d[j]] = o[d[j]] || {};
	            o = o[d[j]];
	        }
	    }
	    return o;
	},
	
    /**
     * Converts this object to its string representation
     * @return string
     */
	toString: function()
	{
        return 'Denbel';
	}
};

// load namespace
Denbel.load( 'lang.StringExtender' );

( function(){
    /**
     * constructor
     * @return void
     */
    Denbel.lang.StringExtender = function(){};
    
    // prototype
    Denbel.lang.StringExtender.prototype =
    {
        /**
         * Encodes the string to UTF-8
         * @return string
         */
        utf8Encode: function()
        {
            var value = this;
            value.replace( /\r\n/g, "\n" );
            var utftext = '';
            var c;
            
            for( var n = 0; n < value.length; n++ )
            {
                c = value.charCodeAt( n );
                
                if( c < 128 )
                {
                    utftext += String.fromCharCode( c );
                }
                else if( ( c > 127 ) && ( c < 2048 ) )
                {
                    utftext += String.fromCharCode( ( c >> 6 ) | 192 );
                    utftext += String.fromCharCode( ( c & 63 ) | 128 );
                }
                else
                {
                    utftext += String.fromCharCode( ( c >> 12 ) | 224 );
                    utftext += String.fromCharCode( ( ( c >> 6 ) & 63 ) | 128 );
                    utftext += String.fromCharCode( ( c & 63 ) | 128 );
                }
            }
            
            return utftext;
        },
        
        /**
         * Decodes the string from UTF-8
         * @return string
         */
        utf8Decode: function()
        {
            var value = this;
            var str = '';
            var i = 0;
            var c = c1 = c2 = 0;
            
            while( i < value.length )
            {
                c = value.charCodeAt( i );
                
                if( c < 128 )
                {
                    str += String.fromCharCode( c );
                }
                else if( ( c > 191 ) && ( c < 224 ) )
                {
                    c2 = value.charCodeAt( i + 1 );
                    str += String.fromCharCode( ( ( c & 31 ) << 6 ) | ( c2 & 63 ) );
                    i += 2;
                }
                else
                {
                    c2 = value.charCodeAt( i + 1 );
                    c3 = value.charCodeAt( i + 2 );
                    str += String.fromCharCode( ( ( c & 15 ) << 12 ) | ( ( c2 & 63 ) << 6 ) | ( c3 & 63 ) );
                    i += 3;
                }
            }
            
            return str;
        }
    };
}() );

// add StringExtender to String class
YAHOO.lang.augmentProto( String, Denbel.lang.StringExtender );

// load util.inArray
Denbel.load( 'util.inArray' );

/**
 * checks if needle is in the haystack array
 * @param mixed needle
 * @param array haystack
 * @param bool set to true to make the return value the index of the needle if found
 * @return bool
 */
Denbel.util.inArray = function( needle, haystack, returnIndex )
{
    if( !haystack || !YAHOO.lang.isArray( haystack ) || haystack.length == 0 )
    {
        return null;
    }
    
    var found = false;
    var index = null;
    
    for( var i = 0; i < haystack.length; i++ )
    {
        if( haystack[i] == needle )
        {
            found = true;
            index = i;
            break;
        }
    }
    
    if( returnIndex && found )
    {
        return index;
    }
    else
    {
        return found;
    }
}

// load util.getHeight
Denbel.load( 'util.getHeight' );

/**
 * Gets the height of an element
 * @param mixed string ID or HTMLElement object
 * @return int height in pixels
 */
Denbel.util.getHeight = function( element )
{
    if( !element )
    {
        return null;
    }
    
    if( YAHOO.lang.isString( element ) )
    {
        element = YAHOO.util.Dom.get( element );
    }
    
    if( !element )
    {
        return null;
    }
    
    return element.offsetHeight;
}

// load util.replaceAll
Denbel.load( 'util.replaceAll' );

/**
 * Replaces all occurances in a string
 * @param string search
 * @param string replace
 * @param string subject
 * @return string
 */
Denbel.util.replaceAll = function( search, replace, subject )
{
    if( !YAHOO.lang.isString( search ) || !YAHOO.lang.isString( replace ) || !YAHOO.lang.isString( subject ) )
    {
        YAHOO.log( 'replaceAll expects three strings as argument', 'error', 'Denbel.util.replaceAll' );
        return subject;
    }
    
    while( subject.indexOf( search ) > -1 )
    {
        subject = subject.replace( search, replace );
    }
    
    return subject;
}

// load util.stripTags
Denbel.load( 'util.stripTags' );

/**
 * Strips all HTML code from a string
 * @param string s
 * @return string
 */
Denbel.util.stripTags = function( s )
{
    return s.replace( /<\/?[^>]+>/gi, '' );
}

// load util.isA
Denbel.load( 'util.isA' );

/**
 * Tests if a given object is of a certain type
 * @param object the object to test
 * @param string the object type to test for
 * @return bool
 */
Denbel.util.isA = function( obj, type )
{
    if( !YAHOO.lang.isString( type ) || !YAHOO.lang.isObject( obj ) )
    {
        YAHOO.log( 'isA( x, y ): invalid data type for argument', 'error' );
        return false;
    }
    
    var r = false;
    
    try
    {
        switch( Denbel.util.BrowserDetect.browser )
        {
            case 'Firefox':
                r = ( ( obj.constructor.toString().toLowerCase() == '[' + type.toLowerCase() + ']' ) ? true : false );
                break;
            
            case 'Explorer':
                if( obj.tagName )
                {
                    var objType = 'HTML' + obj.tagName + 'Element';
                    r = ( ( objType.toLowerCase() == type.toLowerCase() ) ? true : false );
                }
                else
                {
                    r = ( ( obj.toString().toLowerCase() == type.toLowerCase() ) ? true : false );
                }
                break;
            
            case 'Safari':
                r = ( ( obj.toString().toLowerCase() == '[object ' + type.toLowerCase() + ']' ) ? true : false );
                break;
            
            default:
                r = false;
                break;
        }
    }
    catch( e )
    {
        YAHOO.log( 'Error: ' + e, 'error' );
        r = false;
    }
    
    return r;
}

// load namespace
Denbel.load( 'lang.Object' );

( function(){
    /**
     * Denbel.lang.Object
     * Global dynamic object
     * @return void
     */
    Denbel.lang.Object = function()
    {
        this.properties = new Array();
        this.propertyValues = new Array();
    };
    
    // prototype
    Denbel.lang.Object.prototype =
    {
        // fields
        properties: null,
        propertyValues: null,
        
        /**
         * Returns the value of a named property
         * @param string name of the property
         * @return mixed value of the property
         */
        get: function( name )
        {
            var i = Denbel.util.inArray( name, this.properties, true );
            
            if( i == null )
            {
                return null;
            }
            
            return this.propertyValues[i];
        },
        
        /**
         * Sets the value of a named property
         * @param string name of the property
         * @param mixed value of the property
         * @return void
         */
        set: function( name, value )
        {
            var i = Denbel.util.inArray( name, this.properties, true );
            
            if( i )
            {
                this.propertyValues[i] = value;
            }
            else
            {
                this.properties.push( name );
                var newIndex = ( this.properties.length - 1 );
                this.propertyValues[newIndex] = value;
            }
        },
        
        /**
         * Converts this object to an Array
         * @return Array
         */
        toArray: function()
        {
            var arr = new Array();
            
            var v = '';
            var n = '';
            
            for( var i = 0; i < this.properties.length; i++ )
            {
                arr[this.properties[i]] = this.propertyValues[i];
            }
            
            return arr;
        },
        
        /**
         * Converts this object to its string representation
         * @return string
         */
        toString: function()
        {
            return 'Denbel.lang.Object';
        }
    };
}() );

// load namespace
Denbel.load( 'util.BrowserDetect' );

( function(){
	/**
	 * BrowserDetect static object
	 */
	Denbel.util.BrowserDetect =
	{
	    /**
	     * Initializer
	     * @return void
	     */
	    init: function()
	    {
	        this.browser = this.searchString( this.dataBrowser ) || "An unknown browser";
	        this.version = this.searchVersion( navigator.userAgent )
	            || this.searchVersion( navigator.appVersion )
	            || "an unknown version";
	        this.OS = this.searchString( this.dataOS ) || "an unknown OS";
	    },
	    
	    /**
	     * Converts this object to its string representation
	     * @return string
	     */
	    toString: function()
	    {
	        return this.browser + ' ' + this.version + ' ' + this.OS;
	    },
	    
	    searchString: function ( data )
	    {
	        for( var i = 0; i < data.length; i++ )
	        {
	            var dataString = data[i].string;
	            var dataProp = data[i].prop;
	            this.versionSearchString = data[i].versionSearch || data[i].identity;
	            if( dataString )
	            {
	                if( dataString.indexOf( data[i].subString ) != -1 )
	                {
	                    return data[i].identity;
	                }
	            }
	            else if( dataProp )
	            {
	                return data[i].identity;
	            }
	        }
	    },
	    
	    searchVersion: function( dataString )
	    {
	        var index = dataString.indexOf( this.versionSearchString );
	        if( index == -1 )
	        {
	            return;
	        }
	        return parseFloat( dataString.substring( index + this.versionSearchString.length + 1 ) );
	    },
	    
	    dataBrowser: [
	        {   string: navigator.userAgent,
	            subString: "OmniWeb",
	            versionSearch: "OmniWeb/",
	            identity: "OmniWeb"
	        },
	        {
	            string: navigator.vendor,
	            subString: "Apple",
	            identity: "Safari"
	        },
	        {
	            prop: window.opera,
	            identity: "Opera"
	        },
	        {
	            string: navigator.vendor,
	            subString: "iCab",
	            identity: "iCab"
	        },
	        {
	            string: navigator.vendor,
	            subString: "KDE",
	            identity: "Konqueror"
	        },
	        {
	            string: navigator.userAgent,
	            subString: "Firefox",
	            identity: "Firefox"
	        },
	        {
	            string: navigator.vendor,
	            subString: "Camino",
	            identity: "Camino"
	        },
	        {       // for newer Netscapes (6+)
	            string: navigator.userAgent,
	            subString: "Netscape",
	            identity: "Netscape"
	        },
	        {
	            string: navigator.userAgent,
	            subString: "MSIE",
	            identity: "Explorer",
	            versionSearch: "MSIE"
	        },
	        {
	            string: navigator.userAgent,
	            subString: "Gecko",
	            identity: "Mozilla",
	            versionSearch: "rv"
	        },
	        {       // for older Netscapes (4-)
	            string: navigator.userAgent,
	            subString: "Mozilla",
	            identity: "Netscape",
	            versionSearch: "Mozilla"
	        }
	    ],
	    
	    dataOS : [
	        {
	            string: navigator.platform,
	            subString: "Win",
	            identity: "Windows"
	        },
	        {
	            string: navigator.platform,
	            subString: "Mac",
	            identity: "Mac"
	        },
	        {
	            string: navigator.platform,
	            subString: "Linux",
	            identity: "Linux"
	        }
	    ]
	};
}() );

Denbel.util.BrowserDetect.init();
YAHOO.log( 'Browser detected: ' + Denbel.util.BrowserDetect.browser + ' ' + Denbel.util.BrowserDetect.version + ' on ' + Denbel.util.BrowserDetect.OS );
