/**
* (c) 2007 Badneoch-Smith Internet Technolodies Ltd
*/

// Define the name space
if(typeof org == "undefined") { org = {} }
if ( typeof org.bsit == "undefined" ) { org.bsit = {}; }

org.bsit.VERSION = 0.1;
org.bsit.NAME = "org.bsit";

// Global namespace reference
org.bsit.gNamespace = self;
// Search paths to look through
org.bsit.includePath = [".", "js", "js/working", "js/version2.0", "../js/working", "../js/version2.0"];

// Keep a reference to the packages we have loaded
org.bsit.packages = { "org.bsit":org.bsit }

// Store the contextPath incase we need it...
org.bsit.contextPath = "";
/**
* Is the package name defined i.e. loaded already
*/
org.bsit.isDefined = function(name) { return name in org.bsit.packages; }

org.bsit.addToIncludePath = function(a) {
    var tmp = this.includePath.reverse();
    tmp[tmp.length] = a;
    org.bsit.includePath = tmp.reverse();
}

/**
* Borrowed the main functionality from JSAN.js. Finds the path of the
* org.bsit.js file and adds it to the path.
*/
org.bsit.path = function () {
    if (document) {
        var scripts = document.getElementsByTagName('script');
        for ( var i = 0; i < scripts.length; i++ ) {
            var src = scripts[i].getAttribute('src');
            if (src) {
                var inc = src.match(/^(.*?)\/?bsit.js/);
                if (inc && inc[1]) {
                    var p = inc[1];
                    for (var j = 0; j < this.includePath.length; j++) {
                        if (org.bsit.includePath[j] == p) {
                            return;
                        }
                    }
                    this.addToIncludePath(p);
                }
            }
        }
    }
}

org.bsit.path();

/**
* This class should return the correct instance of 
* XMLHttpRequest for the current browser.
* NOTES:
*	1. It might not be too good an idea to use the singleton principle here when returning from getInstance(). As we are reusing the instance, assuming this works the
*		    same way as a static in Java (which I doubt), multiple calls will not work as the _xmlHttpInstance will remain the same object and will probably block.
*
* PARAMS:
*		bwrId - the browser id (infact it's a cut down and nicer version of the window.navigator object) 
*/
org.bsit.AjaxCommsFactory = (function() {
    var that = this;
    var _type = "XMLHttpRequest";
    
    var _instance = function() {
        // Ok first off test for XMLHttpRequest object as this should cover all browsers including
        // IE 7. Otherwise use the antiquated method below ...
        if(window.XMLHttpRequest) { 
            return new XMLHttpRequest();
        }
        var progIDs = ['Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP','Msxml.XMLHTTP']; 
        for (var i = 0; i < progIDs.length; i++) {
            try {
                var xmlDOM = new ActiveXObject(progIDs[i]);
                _type = progIDs[i];
                return xmlDOM;
            }
            catch (ex) {
                _type = null;
                // This should only be part of the debug phases i.e. don't care what the client version is ...
                //alert(ex.message + " exception for type - " + progIDs[i]);
                //throw new Error("XMLHttpRequest not supported. Upgrade browser please!");
            }
        }
        return null;
    }
    
    this.getType = function() { _instance(); return _type; }
    this.getInstance = function() { return _instance(); }
    
    return this;
})();

/**
* NOTES:
*	1. All styling should be done within CSS
*	2. Naming convention should be org.bsit.<script_filename>.<namespace> for namespaces
*/

/**
* Given a document will inject a script file into the header i.e. dynamically 
* loads script file.
*
* PARAMS:
* doc - the document
* url - file url
* sType - i.e. 'text/javascript"
*/ 
org.bsit.injectScript = function(doc, url, sType) {
    var srcScript = doc.createElement("script");
    srcScript.src = url;
    srcScript.type= sType;
    doc.getElementsByTagName("head")[0].appendChild(srcScript); 
    
}

/**
* Given a document will add a style sheet to the header i.e. dynamically 
* apply the style sheet.
*
* PARAMS:
* d - the document
* url - style sheet url
*/
org.bsit.injectStyleSheert = function(doc, url) {
    if(d.createStyleSheet) {
        doc.createStyleSheet(url);
    } else {
    var styles = "@import url('"+url+"');";
    var newSS=document.createElement('link');
    newSS.rel='stylesheet';
    newSS.href='data:text/css,'+escape(styles);
    doc.getElementsByTagName("head")[0].appendChild(newSS);
}
}


/**
* Given a namespace of the form 'somename.somename2.somename3' load each part
* and load the file part from a file somewhere on the includePath. If the package has already 
* been loaded then return it.<b> 
*
* When the package has been created we add it to the global namespace of org.bsit.<b>
*
* If the final parameter is specified then the file is loaded by the using the package structure
* as the directory structure and the final part being the filename.<b> 
*
*	2. Look at http://www.openjsan.org/doc/c/cw/cwest/JSAN/0.10/lib/JSAN.html
* PARAMS:
*	ns - the namespace to look for ...
* packagePath - if set then will use the package naming as the directory structure
*/
org.bsit.requireNamespace = function(ns, packagePath) {
    
    // Split the name up
    var names = ns.split('.');
    // Create a full path to file like in java package naming
    var fullPath = ns.replace(/\./g,"/");
    var filename = "";
    
    // See if we have it defined already
    if(org.bsit.isDefined(ns)) {
        // Already defined
        return org.bsit.packages[ns];
    }
    
    // Create all the namespaces and record the last
    var startNS = org.bsit.gNamespace;
    var def;
    try {
        // If we eval and then object exists then it is returned ...
        def = eval(ns);
    }catch(e) {}
    
    
    // For each name space part
    for(var n=0;n<names.length;n++) {
        if(n == names.length-1) {
            fileName = names[n];
            // Search through the include path looking for a match
            for(var i=0; i<org.bsit.includePath.length;i++) {
                pth = org.bsit.includePath[i];
                if(packagePath)
                    modName = pth + "/" + fullPath + ".js";
                else
                    modName = pth + "/" + fileName + ".js";
                try {
                    var _xmlHttp = this.AjaxCommsFactory.getInstance();
                    _xmlHttp.open("GET", modName, false);
                    _xmlHttp.send(null);
                }catch(ex) { }
                if(_xmlHttp.readyState == 4 && _xmlHttp.status==200) {
                    try {
                        var js = _xmlHttp.responseText;
                        eval(js);
                        break;
                    }catch(e) {}
                }
            }
            
            def = eval(names[n]);
            
            startNS[names[n]] = def;
            
            if(typeof def!="undefined"  && typeof def['prototype']!="undefined")
                startNS[names[n]]['prototype'] = def.prototype;
            
            org.bsit.packages[names.join('.')] = startNS;
            // OK this clean up here means that the logger.LOGGER_LEVEL, etc. stuff
            // won't work as it points to the wrong package if loaded with anything other than logger.
            //delete org.bsit.gNamespace[names[n]];
            return startNS;
        }
        
        // See is we 
        if(typeof startNS[names[n]] == "undefined" && n!=names.length-1) { 
            startNS[names[n]] = {}
        } 
        
        startNS = startNS[names[n]];
        
    }		
    
    
}


