var BF_ALL_NO_CACHE = false;

BFAction = function(incontext) {

	this.context = incontext;
	this.controllers = new Object();
	
	this.init = function(controller) {
		if(! this.controllers[controller]) {
			try {
				eval(controller + '.prototype = new BFController()');	
				eval(controller + '.prototype.constructor = ' + controller);
				var ctl = eval('new ' + controller + '()');
				ctl.setContext(this.context);
				this.controllers[controller] = ctl;
				try {
					ctl.onload();
					ctl.register();
				} catch(e) {
					alert(e + ' on line ' + e.line);
					//DP_Debug.dump(e);
				}
				ctl.controller_name = controller; 				
			} catch(e) {
				// dyna load controller
				if(e.toString().match('is not defined') || e.toString().match("Can't find variable")) {
					this.dynaload(controller);
				} else {
					//DP_Debug.dump(e);
					alert("unable to dyna load controllor: " + controller + ' - ' + e + ' on line ' + e.line);
				}		
			}
		}
	}
	
	// dyna load controller
	this.dynaload = function(controller) {
		var paths = controller.split(/_/);
		var  path = this.context.js_root;
		for(i = 0; i < paths.length; i++) {
			path += paths[i] + '/';
		}
		var js_file = path.replace(/\/$/, '.js');
		var date = new Date();
		js_file += '?date=' + date.getMilliseconds();
		var eval_response = BFgetFile(js_file);
				
		if(eval_response.status == 200) {										
			try {
				eval(eval_response.content);					
				eval(controller + '.prototype = new BFController()');	
				eval(controller + '.prototype.constructor = ' + controller);
				var ctl = eval('new ' + controller + '()');		
				ctl.setContext(this.context);
				try {
					ctl.onload();
					ctl.register();
				} catch(e) {
					alert('unbae to load ctl \'' + controller + '\' ' + e);
				}					
				ctl.setControllerName(controller); 				
				this.controllers[controller] = ctl;
			} catch(e) {
				alert('unable to load contorller ' + controller + ' ' + e);
			}
		} else {
			alert('unable to auto load controller ' + controller + ': ' + eval_response.status);
		}				
	}
	
	this.getController = function(controller, nocache) {
		if(nocache || BF_ALL_NO_CACHE == true) {			
			if(BF_ALL_NO_CACHE == true) {
				DP_Debug.logInfo("nocache dyna loading " + controller);
			}
			this.dynaload(controller);
			ctl = this.controllers[controller];			
		} else {
			var ctl = this.controllers[controller];
			if(! ctl) {
				this.init(controller);
				ctl = this.controllers[controller];
			}
		}
		return ctl;
	}	
}

BFController = function() {

	/* query params */
	this.query_params = null;
	
	/* our controller context */
	this.c = null;	
	
	this.controller_name = null;
	
	/* our loaded templates */
	this.templates = null;
	
	/* loaded objects */
	this.object_cache = new Object();
	
	this.setControllerName = function(cname) {
		this.controller_name = cname;
	}
	
	/* set our context */
	this.setContext = function (context) {
		this.c = context;
	}
	
	/* get query params if any */
	this.params = function() {
		var query = window.location.search.substring(1);
		var vars = query.split("&");
		this.query_params = new Object()
		for (var i=0;i<vars.length;i++) {
			var pair = vars[i].split("=");
   			this.query_params[pair[0]] = unescape(pair[1]);
   			this.query_params[pair[0]] = this.query_params[pair[0]].replace(/\+/g, " ");
  		} 
	}
	
	/* get query paramm by key */
	this.param = function(key) {	
		// TODO does not support mutiple values for one key
		
		// if no params, try and parse them 
		if(! this.query_params) {			
			this.params();
		}
		return this.query_params[key];
	}
	
	this.onload = function() {
		throw('onload() is abstract, must be implemented by a child class');
	}
	
	this.register = function() {
		throw('register() is abstract, must be implemented by a child class');
	}

	this.getTemplate = function(template_string, nocache) {
		if(nocache && BF_ALL_NO_CACHE == true) {
			DP_Debug.logInfo("nocache loading template " + template_string);			
		}
		try {
			if( (nocache && BF_ALL_NO_CACHE ) || ! this.templates || ! this.templates[template_string]) {
				var temlate_path = this.c.trimpath_root + template_string;
				var template_response = BFgetFile(temlate_path);
				if(template_response.status == 200) {
					template = template_response.content;			 
					if(! this.templates) {
						this.templates = new Object();
					}
					this.templates[template_string] = template;
					return template;
				} else {
					alert('unable to load template ' + template_string + ': ' + template_response.status);
				}
			} else {
				return this.templates[template_string];
			}
		} catch(e) {
			alert(e);
		}
	}

	this.getObject = function(oname, nocache) {		
		var obj = null;
		if((nocache && BF_ALL_NO_CACHE) || ! this.object_cache[oname] ) {
			if(nocache && BF_ALL_NO_CACHE) {
				DP_Debug.logInfo("nocache dyna loading object " + oname);
			}
			var paths = oname.split(/_/);
			var  path = this.c.js_root;
			for(i = 0; i < paths.length; i++) {
				path += paths[i] + '/';
			}
			var js_file = path.replace(/\/$/, '.js');
			var date = new Date();
			js_file += '?date=' + date.getMilliseconds();
			var eval_response = BFgetFile(js_file);				
			if(eval_response.status == 200) {										
				try {			
					eval(eval_response.content);
					obj = eval('new ' + oname + '()');	
					this.object_cache[oname] = obj;
				} catch(e) {
					alert('unable to load object ' + oname + ' ' + e);
				}
			} else {
				alert('unable to loadobect ' + oname + ' ' + eval_response.content);
			}
		} else {
			obj = this.object_cache[oname]; 
		}
		return obj;
	}
	
	
	this.templateError = function(resp) {
		alert('Error: unable to fetch trimplath template');
	}

	this.httpRequest = BFgetFile;
	
	this.processTemplate = function(template, data) {
		var result = null;
		try {
			var tp = TrimPath.parseTemplate(template);
			data['_MODIFIERS'] = TT_Filters;
			result = tp.process(data, {throwExceptions:true});
		} catch(e) {
			alert('unable to process trimpath template: ' + e);
		}
		return result;	
	}
}

function BFgetFile(url, params) {
	try {
		var AJAX = null;
		if (window.XMLHttpRequest) {              
			AJAX=new XMLHttpRequest();              
		} else {                                  
			AJAX=new ActiveXObject("Microsoft.XMLHTTP");
		}	
		if(! params) {
			AJAX.open("GET", url, false);                             
			AJAX.setRequestHeader('If-Modified-Since', 'Wed, 15 Nov 1995 00:00:00 GMT');
			AJAX.send(null);
		} else {
			AJAX.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
			AJAX.setRequestHeader('If-Modified-Since', 'Wed, 15 Nov 1995 00:00:00 GMT');
			AJAX.setRequestHeader("Content-length", params.length);
			AJAX.setRequestHeader("Connection", "close");
			AJAX.send(params);  		
		}
		return response = {content:AJAX.responseText, status:AJAX.status }
	} catch(e) {
		alert(e);
	}
}