// JavaScript Document

/**
 *
 * JS Templates Tools
 *
 * @author D.Y <dongyong@linekong.com>
 *
 * @date 2010-11-24
 *
 */
 
var Jtemplate = function() {
	this.tpl;		
	this.data;
	this.js_data = new Array();
	this.left_delimiter = '<!--{';
	this.right_delimiter = '}-->';
	this.tag_section_end = "/section";
}

/**
 * 遍历HTML
 */
Jtemplate.prototype.fetch = function() {

	var limit = 0;

	var s_start = 0;

	var fstart = false;

	var fastobj = new Array();

	var err_limit = 0;
		
	while(true) {

		err_limit++;

		if(err_limit >= 3000) {
			alert("Error: JTemplates System Error. Oh My Lady GaGa! FUCK!!");
			//alert(this.data);
			return false;
		}

		/**
		 * 依次查找 <!-- 如果查找不到，则退出。
		 *
		 */
		if(this.tpl.indexOf(this.left_delimiter) == -1) {
			return false;
		}

		/**
		 * 记录 <!-- 出现的位置
		 *
		 */
		limit = this.tpl.indexOf(this.left_delimiter, limit);

		/**
		 * <!-- 的位置之后
		 *
		 */
		limit += this.left_delimiter.length;

		var start = limit
		var end = this.tpl.indexOf(this.right_delimiter, limit);

		/**
		 *
		 * 获得标记内的内容
		 *
		 */
		var key = this.tpl.substring(start, end);
		var okey = this.left_delimiter + key + this.right_delimiter;

		if(key.charAt(0) == '$') {

			var val = this.getVal(key);

			var str = this.left_delimiter + key + this.right_delimiter;
			str = this.regexp_format(str);
			this.tpl = this.tpl.replace(new RegExp(str, "g"), val);

			var str2 = " " + key + " ";
			str2 = this.regexp_format(str2);
			
			var str3 = " " + key + "}";
			str3 = this.regexp_format(str2);

			if(!isNaN(val)) {
				this.tpl = this.tpl.replace(new RegExp(str2, "g"), " " + val + " ");
				this.tpl = this.tpl.replace(new RegExp(str3, "g"), " " + val + " }");
			}else{
				this.tpl = this.tpl.replace(new RegExp(str2, "g"), " \"" + val + "\" ");
				this.tpl = this.tpl.replace(new RegExp(str3, "g"), " \"" + val + "\" }");
			}
			
			limit = 0;

		}else{

			var tag = this.tpl.substring(limit, this.tpl.indexOf(" ", limit));

			if(tag == 'section') {
				
				var _tmp_html = this.tpl.substr(limit - this.left_delimiter.length);
				var _section_limit = 0;
				var _section_tag_begin = 0;
				var _section_tag_end = 0;
				var _section_while_index = 1;
				while(true) {
					_section_while_index++;
					if(_section_while_index >= 20000) {
						alert('ERROR: section while error');
						break;
					}
					_section_limit = _tmp_html.indexOf(this.left_delimiter, _section_limit);
					_section_limit += this.left_delimiter.length;
					var _section_start = _section_limit
					var _section_end = _tmp_html.indexOf(this.right_delimiter, _section_limit);
					var _section_key = _tmp_html.substring(_section_start, _section_end);
					if(_section_key.charAt(0) == "/") {
						var _section_tag = _section_key.substr(1);
						if(_section_tag == "section") {
							_section_tag_end++;
						}
					}else{
						var _section_tag = _section_key.substring(0, _section_key.indexOf(" "));
						if(_section_tag == "section") {
							_section_tag_begin++;
						}
					}
					if(_section_tag_begin  == _section_tag_end) {
						var header = this.tpl.substring(0, limit - this.left_delimiter.length);
						var content = _tmp_html.substring(0, _section_end + this.right_delimiter.length);
						var footer = _tmp_html.substr(_section_end + this.right_delimiter.length);						
						var l_start = key.indexOf("loop=");
						l_start += 6;
						var l_end = key.indexOf("\"", l_start);
						var loop = key.substring(l_start, l_end);
						var obj = this.getVal(loop);
						var _html = "";
						content = content.substring(okey.length, content.length - this.left_delimiter.length - this.tag_section_end.length - this.right_delimiter.length);
						
						/**
						 * 需要加入循环的index
						 *
						 */
						var _section_index = 0;
						for(s in obj) {
							var _tmp = content;
							var str = loop + ".";
							str = this.regexp_format(str);
							var val = loop + "[" + s + "]" + ".";
							_tmp = _tmp.replace(new RegExp(str, "g"), val);
							_html += _tmp;
							_section_index++;
						}
						this.tpl = header + _html + footer;
						limit = 0;
						break;
					}
				}

			}else if(tag == 'if') {

				var _tmp_html = this.tpl.substr(limit - this.left_delimiter.length);			
				var _if_limit = 0;
				var _if_tag_begin = 0;
				var _if_tag_end = 0;
				var _if_while_index = 1;
				var _else_index = 0;
				var _end_if = '<!--{/if}-->';
				while(true) {
					_if_while_index++;
					if(_if_while_index >= 20000) {
						alert('ERROR: if while error');
						break;
					}
					_if_limit = _tmp_html.indexOf(this.left_delimiter, _if_limit);
					_if_limit += this.left_delimiter.length;
					var _section_start = _if_limit
					var _section_end = _tmp_html.indexOf(this.right_delimiter, _if_limit);
					var _section_key = _tmp_html.substring(_section_start, _section_end);
					if(_section_key.charAt(0) == "/") {
						var _section_tag = _section_key.substr(1);
						if(_section_tag == "if") {
							_if_tag_end++;
						}
					}else{
						if(_section_key == "else") {
							if(_if_tag_begin - 1 == _if_tag_end) {
								_else_index = _section_end;
							}
						}else{
							var _section_tag = _section_key.substring(0, _section_key.indexOf(" "));
							if(_section_tag == "if") {
								_if_tag_begin++;
							}
						}
					}

					if(_if_tag_begin  == _if_tag_end) {
						var header = this.tpl.substring(0, limit - this.left_delimiter.length);
						var content = _tmp_html.substring(0, _section_end + this.right_delimiter.length);
						var footer = _tmp_html.substr(_section_end + this.right_delimiter.length);
						var _expression = key.substr(2);

						var a_key = _expression.split(" ");
						var _expression_val = false;
						for(a in a_key) {
							if(a_key[a].charAt(0) == '$') {
								var val = this.getVal(a_key[a]);

								var str = this.left_delimiter + a_key[a] + this.right_delimiter;
								str = this.regexp_format(str);
								this.tpl = this.tpl.replace(new RegExp(str, "g"), val);

								var str2 = " " + a_key[a] + " ";
								str2 = this.regexp_format(str2);
								
								var str3 = " " + a_key[a] + "}";
								str3 = this.regexp_format(str3);

								if(!isNaN(val)) {
									this.tpl = this.tpl.replace(new RegExp(str2, "g"), " " + val + " ");
									this.tpl = this.tpl.replace(new RegExp(str3, "g"), " " + val + " }");
								}else{
									this.tpl = this.tpl.replace(new RegExp(str2, "g"), " \"" + val + "\" ");
									this.tpl = this.tpl.replace(new RegExp(str3, "g"), " \"" + val + "\" }");
								}

								limit = 0;
								_expression_val = true;
								break;

							}
						}
						
						if(_expression_val) break;
				
						var _html = '';

						if(_else_index != 0) {
							var _if_head = content.substring(okey.length, _else_index - 4 - this.left_delimiter.length);
							var _if_foot = content.substring(_else_index + this.right_delimiter.length, content.lastIndexOf(_end_if));
							try {
								if(eval(_expression)) {
									_html = _if_head;
								}else{
									_html = _if_foot;
								}
							}catch(e) {
								_html = _if_foot;
							}
							
						}else{
							try {
								if(eval(_expression)) {
									_html = content.substring(okey.length, content.lastIndexOf(_end_if));
								}else{
									_html = "";
								}
							}catch(e) {
								_html = "";
							}
						}

						this.tpl = header + _html + footer;

						break;
					}
				}
			}
		}
	}
	/*
	 while end
	*/
}

Jtemplate.prototype.regexp_format = function(str) {
	str = str.replace(/\$/g, "\\$");
	str = str.replace(/\./g, "\\.");
	str = str.replace(/\[/g, "\\[");
	str = str.replace(/\]/g, "\\]");
	return str;
}

Jtemplate.prototype.getVal = function(key) {
	if(key.charAt(0) != '$') return key;
	key = key.substr(1);
	try{
		return eval("this.data." + key);
	}catch(e) {
		return '';
	}
}
Jtemplate.prototype.display = function(tpl, data, callback) {
	this.tpl = tpl;
	this.data = data;
	this.fetch();
	callback(this.tpl);
}
var jtemplate = new Jtemplate();
