var cTemplater = Class.create({
	initialize: function() {
		this.templates = [];
		this.queue = [];
		this.loading = [];
		this.relateds = {
			'init': ['template_start', 'template_menu_search', 'template_movie_history', 'template_ppl_history', 'user_guest', 'user_regged', 'user_toolbar_guest', 'user_toolbar_regged'],
			'template_start': ['template_welcome_news', 'template_welcome_observers', 'template_welcome_rummage', 'template_thumb_movie_big_default'],
			'template_thumb_movie_big_default': ['template_thumb_movie_big_menu', 'template_thumb_movie_big_creatives', 'template_thumb_movie_big_description', 'template_thumb_movie_big_list', 'template_thumb_movie_big_need'],
			'template_thumb_ppl_small_default': ['template_thumb_ppl_small_menu', 'template_thumb_ppl_small_assess', 'template_thumb_ppl_small_im', 'template_thumb_ppl_small_know'],
			'template_messages_list': ['template_out_messages_list'],
			'template_tagelo': ['template_tagelo_lapozo'],
			'template_emberek_menu_lista': ['template_ppl_thumb', 'template_lapozo'],
			'template_movie_big': ['template_ppl_small'],
			'template_ppl_big': ['template_movie_small']
		};
		this.download('init');
	},
	getRelateds: function(name) {
		var ret = [];
		if (name != 'init') {
			ret.push(name);
		}
		var rels = this.relateds[name] || [];
		for (var i=0; i<rels.length; i++) {
			if (!this.isLoading(rels[i])) {
				ret = ret.concat(this.getRelateds(rels[i]));
			}
		}
		return ret;
	},
	// find templates in cache
	// if not exists, try to download
	getTemplate: function(name) {
		//console.log('getTemplate: ' + name);
		var i = 0;
		var template = null;
		for (i = 0; i < this.templates.length; i++) {
			if (this.templates[i].name == name) {
				template = this.templates[i];
			}
		}
		if (template == null && $(name) != null) {
			this.addTemplate({name: name, content: $(name).value});
			template = this.getTemplate(name);
		}
		return template;
	},
	// download templates
	download: function(name) {
		if (this.isLoading(name)) {
			return;
		}
		var related = this.getRelateds(name);
		this.loading = this.loading.concat(related);
		var params = "";
		for (var i=0; i<related.length; i++) {
			params += "name[]=" + related[i] + '&';
		}
		var keres = new Ajax.Request('templater.php', {
			parameters:params,
			method:'get',
			onSuccess: function(transport) {
				var ret = transport.responseText.evalJSON();
				if (typeof ret == 'object') {
					for (var i = 0; i < ret.length; i++) {
						templater.addTemplate(ret[i]);
					}
				}
				else {
					templater.addTemplate(ret);
				}
			},
			onFailure: function() {
				// todo
			}
		});
	},
	downloadAgain: function(name) {
		var keres = new Ajax.Request('templater.php?name='+name, {
		method:'get',
			onSuccess: function(transport) {
				var ret = transport.responseText.evalJSON();
				templater.addTemplate(ret);
			}
		});
	},
	addTemplate: function(template) {
		//console.log('addTemplate begin ' + template.name);
		try {
			var parsed = TrimPath.parseTemplate(template.content);
		} catch(e) {
			//console.log(e);
		}
		//console.log('addTemplate parsed ' + template.name);
		this.templates.push({content: parsed, name: template.name});
		//console.log('addTemplate end ' + template.name);
		// check queue list
		this.checkQueue(template.name, parsed);
	},
	checkQueue: function(name, template) {
		//console.log('checkQueue start ' + name);
		for (var i = 0; i < this.queue.length; i++) {
			if (this.queue[i].name == name) {
				var data = this.queue[i];
				this.processRender(data.targetObject, template, data.data);
				this.queue.splice(i, 1);
				var callback = data.callback;
				if (Object.isFunction(callback)) callback();
			}
		}
	},
	// render
	render: function(target, templateName, data, callback) {
		if (!Object.isElement(target) && !Object.isArray(target)) {
			return;
		}
		// download template if it not exists in cache
		var template = this.getTemplate(templateName);
		if (template == null) {
			this.download(templateName);
			this.queueIt(target, templateName, data, callback);
		} else {
			this.processRender(target, template.content, data);
			if (Object.isFunction(callback)) callback();
		}
	},
	queueIt: function(target, templateName, data, callback) {
		this.queue.push({targetObject: target, name: templateName, data: data, callback: callback});
	},
	isLoading: function(name) {
		if (this.loading.indexOf(name) != -1) {
			return true;
		}
		return false;
	},
	processRender: function(target, template, data) {
		//console.log('processRender begin ' + target.id);
		data._MODIFIERS = myModifiers;
		data.getUsername = function() {return userer.user_name};
		data.getUserSex = function() {return userer.user_nem_style};
		data.getUserId = function() {return userer.user_id};
		/*data.user = {
			isCreativeLike: userer.isCreativeLike.bind(userer)
		};
		data.user = userer;*/
		data.espeak = function(attrib, value, size){
			return embed('codebase','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0','width',size,'height',size,'src','/common/images/espeak_' + size + 'px','quality','high','pluginspage','http://www.macromedia.com/go/getflashplayer','movie','/common/images/espeak_' + size + 'px','wmode','transparent','FlashVars','query='+attrib+'&#61;'+value);
		};
		var targets = target;
		if (!Object.isArray(target)) {
			targets = [target];
		}
		var output = template.process(data);
		//console.log(targets.length);
		for (var i=0; i<targets.length; i++) {
			//targets[i].innerHTML = '';
			targets[i].innerHTML = output || '';
		}
		//console.log('processRender end ' + target.id);	
	},
	bindElements: function(list, fn) {
		for (var i=0; i<list.length; i++) {
			this.bindElement(list[i], fn);
		}
	},
	bindElement: function(element, fn) {
		if (!element) return;
		element.onclick = fn;
	},
	setElements: function(list, attrib, fn) {
		for (var i=0; i<list.length; i++) {
			this.setElement(list[i], attrib, fn);
		}
	},
	setElement: function(element, attrib, fn) {
		if (!element) return;
		element[attrib] = fn;
	},
	observeElement: function(element, event, fn) {
		if (!element) return;
		element.observe(event, fn);
	},
	observeElements: function(element, event, fn) {
		if (!element) return;
		for (var i=0; i<element.length; i++) {
			this.observeElement(element[i], event, fn);
		}
	}
});
