/*  www.js.genshi2js
    ~~~~~~~~~~~~~~~~

    This javascript module harbors three helpers.

    :slice: which is a python semantical slicing.
    :call: which takes a function and one argument and calls
    that function withthat argument
    :dynamic_attributes: takes an object and turns it into
    an attribute string

    :copyright: 2006 by Florian Boesch.
    :license: GNU LGPL, see LICENSE for more details.
*/

genshi2js = {
    Stream : function(stream){
        var self = this;
        self.stream = stream;
        self.serialize = function(){
            return self.stream.join('');
        }
    },
    stream : function(data){
        return new genshi2js.Stream([data]);
    },
    merge:function(){
        var result = {};
        for(var i=0; i<arguments.length; i++){
            obj = arguments[i];
            for(name in obj){
                result[name] = obj[name];
            }
        }
        return result;
    },
    clone:function(obj){
        var result = {};
        for(name in obj){
            result[name] = obj[name];
        }
        return result;
    },
    slice:function(seq, start, stop, step){
        var length = seq.length
        if(step > 0 || step == null){
            var corr = 0
            var up = length
            var low = 0
            var compare = function(a, b){return a<b}
        }
        else if(step < 0){
            var corr = 1
            var up = 0
            var low = length
            var compare = function(a, b){return a>b}
        }
        var correct = function(value, fill)
        {
            if(value == null){
                return fill
            }
            else if(value < 0){
                var result = value + length + corr
            }
            else{
                var result = value + corr
            }
            if(result < 0){
                return 0
            }
            else if(result > length){
                return length
            }
            else{
                return result
            }
        }

        start = correct(start, low)
        stop = correct(stop, up)

        if(step == null){
            return seq.slice(start, stop)
        }
        else{
            result = new Array()
            for(var i = start - corr; compare(i, stop - corr); i+= step){
                result.push(seq[i])
            }
            return result
        }

    },
    dynamic_attributes:function(data){
        var data = items(data)
        var result = new Array()
        for(var i=0; i<data.length; i++)
        {
            var item = data[i];
            if(item[1]){
                result.push(item[0] + '="' + item[1] + '"');
            }
        }
        return result.join(" ")
    },
    attribute:function(name, data){
        if(data){
            return ' ' + name + '="' + data + '"';
        }
        else{
            return '';
        }
    },
    iterate:function(seq, fun){
        if(seq){
            for(var i=0; i < seq.length; i++){
                fun(seq[i])
            }
        }
    },
    do_call:function(element, callable, data){
        var data = evalJSON(data);
        return callable.apply(element, data);
    },
    util:{
        enumerate:function(seq, start){
            start = start ? start : 0
            result = new Array()
            if(seq){
                for(var i=0; i < seq.length; i++){
                    result.push([i+start, seq[i]])
                }
                return result
            }
        },
        len:function(seq){
            return seq.length;
        },
        range:function(size){
            var result = new Array();
            for(var i=0; i<size; i++){
                result.push(i);
            }
            return result;
        },
        stringify:function(value){
            return "'" + genshi2js.util.escape(value) + "'";
        },
        escape:function(value){
            return escape(value)
                .replace(/\//g,"%2F")
                .replace(/\?/g,"%3F")
                .replace(/=/g,"%3D")
                .replace(/&/g,"%26")
                .replace(/@/g,"%40");
        },
        unescape:function(value){
            return unescape(value
                .replace(/%40/g, '@')
                .replace(/%26/g, '&')
                .replace(/%3D/g, '=')
                .replace(/%3F/g, '?')
                .replace(/%2F/g, '/')
            );
        },
        call:function(name){
            var data = serializeJSON(genshi2js.slice(list(arguments), 1));
            var data = "'" + data.replace(/"/g, "\\'") + "'";
            var result = 'return genshi2js.do_call(this,' + name + ',' + data + ')';
            return result;
        }
    }
}

genshi2js.fill_vars = function(ns, stack, result_html){
    var html_escape = function(data){
        if(data.toString){
            var data = data.toString();
        }
        return data
            .replace(/&/g,"&amp;")
            .replace(/</g,"&lt;")
            .replace(/>/g,"&gt;");
    }
    var locals = {
        html_push:function(markup){
            result_html.push(markup);
        },
        secure_push:function(data){
            if(!(data === null || data === undefined)){
                if(data.stream){
                    for(var i=0; i<data.stream.length; i++){
                        result_html.push(data.stream[i]);
                    }
                }
                else{
                    result_html.push(html_escape(data));
                }
            }
        },
        stack_increment:function(ns){stack.push(ns);return genshi2js.clone(ns)},
        stack_decrement:function(){return stack.pop()}
    }
    
    locals.p = Math.pow;
    locals.s = genshi2js.slice;
    locals.a = genshi2js.dynamic_attributes;
    locals.it = genshi2js.iterate;
    locals.h = locals.html_push;
    locals.sp = locals.secure_push;
    locals.i = locals.stack_increment;
    locals.d = locals.stack_decrement;
    ns.genshi2js = genshi2js;
    ns.log = function(data){
        console.log(data);
        return data;
    }
    return locals;
}
