/*
 *   Depends:
 *	ui.core.js
 */

(function($) {


    function text_exp(exp_str) {
        this.inheritFrom = exp;
        this.inheritFrom();
        this.eval = function(data, for_index) {
            return exp_str;
        };
    }

    function cycle_exp(exp_str) {
        this.inheritFrom = exp;
        this.inheritFrom();
        this.even_text = null;
        this.odd_text = null;
        this.my_cycle_reg = /\[\[\s*cycle\s+(.*?)\s+(.*?)\s*\]\]/;

        this.code_gen = function() {
            var regex_r = this.my_cycle_reg.exec(exp_str);
            this.even_text = regex_r[1];
            this.odd_text = regex_r[2];
        };

        this.eval = function(data, for_index) {

            if (for_index % 2 == 0) {
                // even
                var r = this.even_text;
            } else {
                // odd
                var r = this.odd_text;
            }
            return r;
        };
    }

    function var_exp(exp_str) {
        this.inheritFrom = exp;
        this.inheritFrom();
        this.key_reg = /\[\=(.*?)\]/;
        this.var_ref_reg = /(.*?)\.(.*)/,

        this.code = null;
        this.code_gen = function() {
            var key_str = exp_str.match(this.key_reg)[1];
            var key_list = key_str.split(".");

            this.code = 'data';

            for (var i = 0; i < key_list.length; i++) {
                this.code += '["' + key_list[i] + '"]';
            }
            //this.code = 'data["' + key[1] + '"]';
        };

        this.eval = function(data, for_index) {
            var r = eval(this.code);
            if (r == undefined) return "";
            return r;
        };
    }

    function for_exp(exp_str) {
        this.inheritFrom = exp;
        this.inheritFrom();
        this.content_reg = /^\[\[\s*for.*?\]\](.*?)\[\[\s*endfor\s*\]\]$/;
        this.for_item_reg = /\[\[\s*for\s+(.*?)\s+in\s+(.*?)\]\].*/;

        this.code = null;
        this.code_gen = function() {
            var for_regex_r = this.for_item_reg.exec(exp_str);
            var for_item_str = for_regex_r[1].split(" ").join("");
            var for_data_str = for_regex_r[2].split(" ").join("");
            var content_str = this.content_reg.exec(exp_str)[1];

            var ex = new exp(content_str);
            ex.code_gen();
            this._children.push(ex);

            //       var r = "";
            this.code = "var r = '';" +
            //"alert(data['"+ for_data_str +"']);"+
            "var d = data['" + for_data_str + "'];" + "for(var i = 0 ; i < d.length; i++)" + "{" + "var item = d[i];" + "var param = {" + for_item_str + ":item};" + "for(var key in data)" + "{" + "param[key] = data[key];" + "}" + "var children_str = '';" + "for(var j =0 ; j < this._children.length; j++)" + "{" + "children_str += this._children[j].eval(param, i);" + "}" + "r += children_str;" + "}" + "r;";

        };

        this.eval = function(data, for_index) {
            var r = eval(this.code);
            return r;
        };
    }

    function exp(exp_str) {
        //     this.token_reg = /\[\[\s*for\s+.*?\[\[endfor\]\]|\[\=.*?\]/g,
        //     this.token_reg = /\[\[\s*for\s+.*?\]\]|\[\[\s*endfor\s*\]\]|\[\=.*?\]/g,
        //     this.for_reg = /\[\[\s*for\s+.*?\[\[endfor\]\]/,
        this.token_reg = /\[\=.*?\]|\[\[\s*for\s+.*?\]\]|\[\[\s*endfor\s*\]\]|\[\[\s*cycle\s+.*?\]\]|[^\[\]]+/g, this.for_reg = /\[\[\s*for\s+.*?\]\]/, this.end_for_reg = /\[\[\s*endfor\s*\]\]/, this.var_reg = /\[\=.*?\]/, this.cycle_reg = /\[\[\s*cycle\s+.*?\s*\]\]/,
        //     this.token_reg = new RegExp("\[\[\s*for\s+.*?\[\[endfor\]\]|\[\=.*?\]", "g");
        //     this.for_reg = new RegExp("\[\[\s*for\s+.*?\[\[endfor\]\]", "g");
        //     this.var_reg = new RegExp("\[\=.*?\]", "g");
        this._exp_str = exp_str; //for debugging
        this._children = [];

        this.code_gen = function() {

            var token_list = exp_str.match(this.token_reg);
            var begin_idx, end_idx = 0;
            for (var i = 0; i < token_list.length; i++) {
                if (this.for_reg.test(token_list[i])) {
                    //need to find endfor.
                    var counter = 1;
                    var for_block_str = token_list[i];
                    for (i += 1; i < token_list.length; i++) {
                        var end_for_candidate_token = token_list[i];
                        if (this.for_reg.test(end_for_candidate_token)) {
                            counter++;
                        } else if (this.end_for_reg.test(end_for_candidate_token)) {
                            counter--;
                        }
                        for_block_str += end_for_candidate_token;

                        if (counter == 0) {
                            var f_exp = new for_exp(for_block_str);
                            f_exp.code_gen();
                            this._children.push(f_exp);
                            break;
                        }
                    } // for
                } else if (this.var_reg.test(token_list[i])) {
                    var v_exp = new var_exp(token_list[i]);
                    v_exp.code_gen();
                    this._children.push(v_exp);
                } else if (this.cycle_reg.test(token_list[i])) {
                    var c_exp = new cycle_exp(token_list[i]);
                    c_exp.code_gen();
                    this._children.push(c_exp);
                } else {
                    //plain text
                    var t_exp = new text_exp(token_list[i]);
                    this._children.push(t_exp);
                }

            } // for
        };

        this.eval = function(data, for_index) {
            var r = "";
            for (var i = 0; i < this._children.length; i++) {
                r += this._children[i].eval(data, for_index);
            }
            return r;
        };
    };

    var KtTemplate = {

        root_exp: null,

        _init: function() {
            var e = new exp(this.options['template']);
            e.code_gen();
            this.root_exp = e;
        },

        render: function(params) {
            var r = this.root_exp.eval(params);
            $(this.element).append(r);
            $(this.element).trigger('render_complete', params);
        },

        renderPrepend: function(params) {
            var r = this.root_exp.eval(params);
            $(this.element).prepend(r);
        },

        clear: function(params) {
            $(this.element).empty();
        }

    };



    $.widget("kt.ktTemplate", KtTemplate);

})(jQuery);

