/**
 * JavaScript Template System
 * Added to the String object, so any string can be templated using the "data"
 *
 * @author Alin Voiculescu
 *
 * @param data The object data that is inserted into the string
 * @return string
 */
String.prototype.present = function (data) {

    /* p = position */
    /* d = depth */
    var p = 0, d = 0, z,
    chr, str = this,

    /**
     * Searches for a variable in the object "r" by it's name, using a dot.syntax in a string
     * Example:
     * r = {
     *    dot: {
     *        syntax: "some value"
     *    }
     * }
     * when vn = "dot.syntax", the function will return "some value"
     */
    srchvar = function(vn,r,whennotfound) {

        var p = vn.split('.'),s;
        try {
            for(s in p) {
                r = r[p[s]];
            }
        } catch(e) {
            if (typeof whennotfound === 'undefined') {
                r = '';
            }
            else {
                r = whennotfound;
            }
        }
        return r;
    },

    /**
     * Scans the {interior} of a pair of brackets, and returns the proper data for that pair
     */
    parsepair = function (start,stop) {
    
		var vname, res, j={}, key, row, keyn, varn, ret='', kw,
		limitkw = function(limit) {
			for(var y in kw) {
				if(y>limit) {
					kw[limit]+=':' + kw[y];
					delete kw[y];
				}
			}
		};
		
		// special keyword follows
		if(str.charAt(start) == '%') { 
			
			kw = str.substr(start+1,stop-start-1).split(':');
			
			switch(kw[0]) {
				// "loop" - repeats the content depending on an array of values
				case 'loop': 
					
					limitkw(4);
					// search the var in kw[1]
					j = srchvar(kw[1],data,''); // j = data in the found var | variant: '{'+kw[1]+'}' = show marker {} instead of empty ''
					
					keyn = kw[2];
					varn = kw[3];
					
					for(key in j) {
						
						data[keyn]=key;
						data[varn]=j[key];
						
						ret += kw[4].present(data); // recursively call present for loop content
					}
					return ret;
				// "exists" - if variable exists, the inside is displayed, if not it just returns nothing
				case 'exists':
					
					limitkw(2);
					// search the var in kw[1]
					j = srchvar(kw[1],data,false);
					
					if(j) { // if succeeds, var exists
						return kw[2].present(data);
					} else {
						return '';
					}
/* // Disabled for now
				// "section" - saves a fragment of the template for later use
				case 'section':
					limitkw(2);
					
					key = kw[1];
					solcon.tpl_cache[key]=kw[2];
					
					return kw[2].present(data);
*/
				// TODO: Other features of the template engine
			}			

		// simple variable replace			
		} else if(str.charAt(start) == '$') { 
			vname = str.substr(start+1,stop-start-1); 
			res = srchvar(vname,data,''); // variant: show marker: '{'+vname+'}' (instead of empty '')
			return typeof res === 'string' || typeof res === 'number' ? res : vname; // variant: '{'+vname+'}'			
		} else {
			return '{'+str.substr(start,stop-start)+'}';
		}
    },

    /**
     * Searches the paired bracket } for the one at position P
     */
    searchpair = function () {

        var pf = p, chr, df = d + 1;

        /* keep searching while increasing df by one for each { found, and decreasing for each } found */
        do {
            chr = str.charAt(pf++);
            if (chr == '{') {
                df = df + 1;
            }
            if (chr == '}') {
                df = df - 1;
            }

            if (df == d) {
                break;
            }
        } while(pf<str.length);

        return pf-1;
    },

    start, stop, ret = '';

    // scans for { character inside string ( this )
    do {
        chr = str.charAt(p++);
        if(chr == '{') {
            z = searchpair ();
            ret += parsepair (p,z);
            p = z+1;
        } else {
            ret += chr;
        }
    } while(p<this.length);

    return ret;
};

/**
 * 
 * DonReY Singleton, provides some useful functions
 * Add application code here
 */
var donrey={

	/**
	 * Creates a delay in execution of a function
	 * If smart_delay is called with the same "key" before the timeout has expired,
	 *   the previous timeout is cleared and a new one is created ( delay the func even further )
	 * It is possible to call smart_delay without the function ( if it was defined earlier ) 
	 */
	delay_keys: {},
	smart_delay: function(key,func,delay,func_args) {

		var that = this;
		
		// clear the old timeout if it exists with the same key
		if(this.delay_keys[key]) {
			clearTimeout(this.delay_keys[key].to_id);
		} else
			this.delay_keys[key]={};
		// create the timeout with the specified function
		if(func) {
			this.delay_keys[key].func = func;
			this.delay_keys[key].func_args = func_args;
		}
		if(delay) {
			this.delay_keys[key].delay = delay;
		}
		this.delay_keys[key].to_id=setTimeout(function() {
			// call the function if it was defined properly
			if(that.delay_keys[key].func && typeof that.delay_keys[key].func == 'function')
				that.delay_keys[key].func(that.delay_keys[key].func_args);
			delete that.delay_keys[key];
		},this.delay_keys[key].delay);
	},

	/**
	 * Cancels a pending execution of a function, by specifying it's key
	 */
	cancel_delay: function(key,keep) {
		if(this.delay_keys[key]) {
			clearTimeout(this.delay_keys[key].to_id);
			if(!keep)
				delete this.delay_keys[key];
		}
	},
	
    /**
     * Compares two arrays if they are identical
     */
    array_compare: function(a1,a2) {
        if (a1.length != a2.length) return false;
        for (var i = 0; i < a2.length; i++) {
            if (a1[i].compare) { 
                if (!a1[i].compare(a2[i])) return false;
            }
            if (a1[i] !== a2[i]) return false;
        }
        return true;
    }

};

/**
 * DonReY "base" object, contains functions to help with JS inheritance
 */
donrey.BASE = {
	// adds public members to the object just created ( when extending )
	_public: function(o) {
		if(typeof o == 'object') {
			for(var i in o)
				this[i]=o[i];
		}
	},
	// extends the object ( just like class extension in classical inheritance )
	_extend: function(F,i) {
		F = F || function() {};
		F.prototype = this;
		var o = new F();
		o._construct(i);
		return o;
	},
	// default constructor, overwrite this with specialized constructors
	_construct: function() {
	}
};

/**
 * DonReY Configuration
 * - Add configs for the application in this object
 */
donrey.config = {
    debug: true
};

/**
 * firebug call wrapper (for debugging)
 *
 * @param o Object to dump
 * @param cmd Mode
 * @return
 */
dump = function(o, cmd) {

	// "p" not used atm
	if(cmd === undefined)
		cmd = 'log';
	
	if(console[cmd]&&donrey.config.debug) {
		console[cmd](o);
	}
};

function getCookie(c_name) {
	
	if (document.cookie.length>0) {
		c_start=document.cookie.indexOf(c_name + "=");
		if (c_start!=-1) {
		    c_start=c_start + c_name.length+1;
		    c_end=document.cookie.indexOf(";",c_start);
		    	if (c_end==-1) c_end=document.cookie.length;
	    		return unescape(document.cookie.substring(c_start,c_end));
		}
	}
	return "";
}
