// simple template
// original: livedoor gourmet
// http://gourmet.livedoor.com/js/lite/common.js
(function () {
    var F = window.Folkat;
    F.Template = function (str){
        this.stash = {
            pre : {},
            params : {}
        };
        this.filters = [];
        this.filter_for_param = {};
        this.use_filter = false;
        if (str) {
            this.init(str)
        }
    }
    F.Template.prototype = {
        isTemplate: true,
        init: function(str) {
            if(str.isTemplate){
                str = str.tmpl;
            }
            this.tmpl = str;
            if(str.charAt(0) == "$"){
                var el = $(str.slice(1));
                this.tmpl = (el.tagName == "textarea") ? el.value : el.innerHTML;
            }
        },
        fill: function(){
            var args = $A(arguments);
            var builder = this.compile();
            return builder.apply(this,args);
        },
        pre_fill : function(){
            
        },
        add_filter: function(expr,filter){
            this.use_filter = true;
            if(expr.isString){
                var f = this.filter_for_param;
                f[expr] ? f[expr].push(filter) : (f[expr] = [filter]);
                return;
            }
            if(expr.isFunction){
                var f = function(value){return filter(value)};
                f.gate = expr;
                this.filters.push(f)
            }
        },
        add_filters : function(o){
            var self = this;
            $.each(o, function(key, value) {
                self.add_filter(key,value)
            });
        },
        get_param : function(key){
            var params = this.stash.params;
            var pre = this.stash.pre;
            if(params.hasOwnProperty(key))
                return params[key]
            else if(pre.hasOwnProperty(key))
                return pre[key]
            return null;
        },
        filtered: function(key){
            var self  = this;
            var value = this.get_param(key);
            var res = value;
            // filters
            if(this.filters.length){
                this.filters.forEach(function(filter){
                    if(filter.gate.call(self,value,key,self))
                        res = filter.call(self,res,key,self)
                })
            } else if(this.filter_for_param[key]){
                this.filter_for_param[key].forEach(function(filter){
                    res = filter.call(self,res,key,self)
                })
            }
            return res;
        },
        make_builder: function(buffer_ref){
            var self = this;
            var buf  = buffer_ref;
            return function(){
                //            var args = $A(arguments);
                self.stash.params = {};
                $.each(arguments, function(i, p){
                    $.each(p, function (k, v) {
                        v && $.each(v, function (k2, v2) {
                            self.stash.params[ k + '_' + k2 ] = v2;
                        });
                    });
                    $.each(p, function(k, v) {
                        self.stash.params[k] = v;
                    });
                });
                return buf.join("");
            };
        },
        compile: function(pre_vars){
            var self = this;
            var buf = [];
            var builder = this.make_builder(buf);
            var sep = /\[\[(.*?)\]\]/g;
            var offset = 0;
            var tmpl = this.tmpl;
            tmpl.replace(sep, function(){
                var a = arguments;
                var stash = self.stash;
                var match_text = a[0];
                var match_idx = a[2];
                var key = a[1];
                buf.push(tmpl.slice(offset,match_idx));
                offset = match_idx + match_text.length;
                var n = {};
                // function
                if(key.charAt(0) == "#" && key.charAt(1) == '#'){
                    var context = [];
                    var expr = key.match(/%(.*?)%/)[1];
                    context.push("var retval; with(this.params){try { retval=(");
                    context.push(expr);
                    context.push(")} catch(e) { Folkat.debug(e); return ''; }; return retval }");
//                    context.push(")} catch(e) { return ''; }; return retval }");
//                    F.debug(context.join(""));
                    var func = new Function(context.join(""));
                    n.toString = function () {
                        var str = func.apply(stash, arguments);
                        return str;
                    };
                }
                else if(key.charAt(0) == "#"){
                    var context = [];
                    var expr = key.match(/%(.*?)%/)[1];
                    context.push("var retval; with(this.params){try { retval=(");
                    context.push(expr);
                    context.push(")} catch(e) { Folkat.debug(e); return ''; }; return retval }");
//                    context.push(")} catch(e) { return ''; }; return retval }");
//                    F.debug(context.join(""));
                    var func = new Function(context.join(""));
                    n.toString = function () {
                        var str = F.Template.escape(func.apply(stash, arguments));
                        return str;
                    };
                } else {
                    n.toString = function(){
                        var expr = stash.params[key];
                        var res = (expr != null) ?
                            (expr.isFunction) 
                            ? "" + expr()
                            : "" + self.filtered(key) 
                        : "";
                        return F.Template.escape(res);
                    }
                };
                buf.push(n);
            });
//	    F.debug(buf);

            buf.push(tmpl.slice(offset));
            return builder;
        }
    };
    F.Template.get = function(id){
        //    var el = $(id);
        var el = document.getElementById(id);
        var is_textarea = (el.tagName.toLowerCase() == "textarea");
        var v = is_textarea ? el.value : el.innerHTML;
        return new F.Template(v);
    }
    F.Template.escape = function(str) {
        return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); //");
    }; 
})();

