HD.util.Template = function(config) {
	this.config = config;
	this.loadTemplates(arguments.callee);
};

HD.util.Template.prototype = {
	processTemplate : function(template, contextObject, optionalFlags) {
		// Set up context presets.
		contextObject = HD.merge(this.TEMPLATE_CONTEXT, contextObject || {});
		contextObject._MODIFIERS = HD.merge(this.TEMPLATE_MODIFIERS, contextObject._MODIFIERS || {});
		
		// Return processed template.
		return template.process(contextObject, optionalFlags);
	},
	
	loadTemplates : function(/* constructor or */ defaultTemplates, defaultHooks, override, byReference) {
		var self = this, common = HD.util.Common, error = HD.ERRORS;
		
		// If the constructor was passed, grab templates/hooks manually.
		if (typeof defaultTemplates == 'function') {
			var fn = defaultTemplates;
			defaultTemplates = fn.templates;
			defaultHooks = fn.hooks;
		}
		
		// Set the templates/hooks objects.
		if (override) {
			this.config = this.config || {};
			this.config.dateFormat = this.config.dateFormat || override.config.dateFormat || null;
			this.config.templates = HD.merge(HD.clone(defaultTemplates || {}, true), (override.config || this.config)[override.templates] || {});
			this.config.hooks = HD.merge(HD.clone(defaultHooks || {}, true), (override.config || this.config)[override.hooks] || {});
		}
		else if (!byReference) {
			this.config.templates = HD.merge(HD.clone(defaultTemplates || {}, true), this.config.templates || {});
			this.config.hooks = HD.merge(HD.clone(defaultHooks || {}, true), this.config.hooks || {});
		}
		
		this.TEMPLATE_CONTEXT = {
    		classes    : HD.CSS_CLASSES,
			config     : this.config || {},
			hooks      : this.config ? this.config.hooks || {} : {},
			templates  : this.config ? this.config.templates || {} : {}
		};	
		this.TEMPLATE_MODIFIERS = {
			date       : function(date) { return HD.util.Date.format(date, self.config.dateFormat || ''); },
			ellipse    : function() { return common.ellipseText.apply(common, arguments); },
			facade     : function(media) { return (media && media.facade.getHtml(self.config, self.model)) || ''; },
			round      : function() { return common.round.apply(common, arguments); },
			strip      : function() { return common.stripHtmlTags.apply(common, arguments); },
			trim       : function() { return common.trim.apply(common, arguments); },
			sortErrors : function() { return error.sortErrors.apply(error, arguments); },
			selectErrors : function() { return error.selectErrors.apply(error, arguments); },
			hasError   : function() { return error.hasError.apply(error, arguments); },
			getError   : function() { return error.getError.apply(error, arguments); }
		};
	},
	
	// Simple alias to retrieve child elements by a hook, scope for applied functions is set to 'this'.
	getByHook: function(hook, apply, elementType, containerEl) {
		return HD.getByClass(this.config.hooks[hook], elementType || '*', containerEl || this.getParent(), apply || null);
	}
};

HD.register('hd_template', HD.util.Template, {version: "1.0", build: "1"});
