/*
    Code from Douglas Crockford
    www.crockford.com
*/
Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

/*
    Code from Douglas Crockford
    www.crockford.com
*/
Function.method('inherits', function (parent, useClass) {
    var d = 0;

    var p = (useClass) ? (this.prototype = parent) : (this.prototype = new parent());

    this.method('uber', function uber(name) {
        var f = null;
        var r = null;
        var t = d;
        var v = parent.prototype;
        if (t) {
            while (t) {
                v = v.constructor.prototype;
                t -= 1;
            }
            f = v[name];
        } else {
            f = p[name];
            if (f == this[name]) {
                f = v[name];
            }
        }
        d += 1;
        r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
        d -= 1;
        return r;
    });
    return this;
});


var Doubleyou = (function(){

    /*private static properties*/
    var $toString = 'Doubleyou.core';

    //Base href for script files
    var $basePath = null;

    //Reference to current document
    var $doc = window.document;

    //Modules loaded
    var $modules = new Object();

    //http connections used to import javascript files
    var $httpRequest = new Array();

    //Determines if the application is running through http or not.
    var $onlineMode = (location.host != '');

    /*private static methods*/

    /*Constructor function*/
    constructorFn = function(){}

    /*privileged static (class) methods*/
    constructorFn.getBasePath = function(){
        return $basePath;
    }

    constructorFn.setBasePath = function(path){
        if (path != null) $basePath = path;
        else{
            var scripts = this.getTags('script');

            var core = null;
            var n = scripts.length;
            for (var i = 0; i < n; i++){
                if (scripts[i].src.lastIndexOf('doubleyou/core.js') > -1){
                    core = scripts[i].src;
                    break;
                }
            }

            $basePath = core.substring(0, core.lastIndexOf('doubleyou/core.js'));
        }

        return $basePath;
    }

    constructorFn.getOnlineMode = function(){
        return $onlineMode;
    }

    constructorFn.registerModule = function(module){
        $modules[module.toString()] = module;
    }

    constructorFn.getModules = function(){
        return $modules;
    }

    constructorFn.getHttp = function(){
        //If no httpRequest has been instantiated, do it now
        if ($httpRequest.length == 0) {
            $httpRequest[0] = new this.httpRequest();
            return $httpRequest[0];
        }

        //Check for a non used httpRequest
        var n = $httpRequest.length;
        var available = null;
        for (var i = 0; i < n; i++){
            if ($httpRequest[i].getState != 'loading'){
                available = $httpRequest[i];
                break;
            }
        }

        if (available != null) return available;

        $httpRequest[n] = new this.httpRequest();
        return $httpRequest[n];

    }

    constructorFn.getFile = function(url, headers) {
        var http = this.getHttp();
        return http.load(url, headers);
    }


    constructorFn.getDocument = function(){
        return $doc;
    }

    constructorFn.getElement = function(){
        var elms = new Array();

        var n = arguments.length;

        var d = this.getDocument();

        for (var i = 0; i < n; i++){
            var elm = arguments[i];
            if (typeof elm == 'string') elm = d.getElementById(elm);

            if (n == 1) return elm;

            elms.push(elm);
        }

        return elms;
    }

    constructorFn.toString = function(){
        return $toString;
    }

    return constructorFn;

})();





Doubleyou.getTags = function(name, root, level){
	if (!level){
	    if (!root) return this.getDocument().getElementsByTagName(name);
    	else return this.getElement(root).getElementsByTagName(name);
    }
    else{
		var elm = (root == 'body') ? this.getTags('body')[0] : this.getElement(root);
		var tag = name.toLowerCase();
		var tags = new Array();
		//Si sólo queremos las de primer nivel
		if (level == 1){
			var nodes = elm.childNodes;
			for (var i = 0; i < nodes.length; i++){
				if (nodes[i].tagName && nodes[i].tagName.toLowerCase() == tag) tags.push(nodes[i]);
			}
		}

		return tags;
    }
}

Doubleyou.requires = function(){
    var n = arguments.length;
    for (var i = 0; i < n; i++){
        if (!this.checkModuleLoaded(arguments[i])) this.importModule(arguments[i]);
    }

}

Doubleyou.checkModuleLoaded = function(name){
    var modules = this.getModules();
    var loaded = false;

    for (var i in modules){
        if (modules[i].toString() == name) loaded = true;
    }

    return loaded;
}

Doubleyou.importModule = function(name){
    var base = this.getBasePath();

    if (base == null) base = this.setBasePath();


    var name = name.split('.').join('/');
    name+='.js';

    var url = base+name;

    var module = this.getFile(url);
    eval(module);
}

Doubleyou.addEvent = function(elementObject, eventName, functionObject){
	var functions = Array.prototype.slice.apply(arguments, [2]);

	var elm = this.getElement(elementObject);

	for (var i = 0; i < functions.length; i++){
	    if(document.addEventListener) elm.addEventListener(eventName, functions[i], false);
    	else if(document.attachEvent) elm.attachEvent("on" + eventName, functions[i]);
    }
}

Doubleyou.getEventSource = function(e){
	return (window.event) ? window.event.srcElement : e.target;
}

Doubleyou.getAttribute = function(elm, name){
	var elm = this.getElement(elm);

	if (elm.getAttributeNode) return elm.getAttributeNode(name).value;
	else return elm.getAttribute(name);
}


var DY = Doubleyou;


Doubleyou.httpRequest = function(){
    var obj;
    try{ //to get the mozilla httprequest object
        obj = new XMLHttpRequest();
    }
    catch(e){
        try{ //to get MS HTTP request object
            obj=new ActiveXObject("Msxml2.XMLHTTP.4.0");
        }
        catch(e){
            try{ //to get MS HTTP request object
                obj=new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch(e){
                try{// to get the old MS HTTP request object
                    obj = new ActiveXObject("microsoft.XMLHTTP");
                }
                catch(e){
                    //throw new mod.Exception("Unable to get an HTTP request object.");
                }
            }
        }
    }

    this.getHttp = function(){
        return obj;
    }


}

Doubleyou.httpRequest.prototype.getState = function(){
    var state = this.getHttp().readyState;

    if (state == 0) return 'uninitialized';
    if (state == 1) return 'loading';
    if (state == 2) return 'loaded';
    if (state == 3) return 'interactive';
    if (state == 4) return 'completed';
}

Doubleyou.httpRequest.prototype.load = function(url, headers){
    //if callback is defined then the operation is done async
    var headers = (headers != null) ? headers : [];
    //setup the request
    try{
        var obj = this.getHttp();
        obj.open("GET", url, false);

        for(var i=0;i< headers.length;i++){
            obj.setRequestHeader(headers[i][0], headers[i][1]);
        }

        obj.send("");

    }catch(e){
        //throw new DY.Exception("Unable to load URL: '%s'.".format(url), e);
    }


    if(obj.status == 200 || obj.status == 0){
        return obj.responseText;
    }else{
          //throw new DY.Exception("File not loaded: '%s'.".format(url));
    }
}

