var pxl = {
    license: 'copy-it-right',

    fonts: {},

    font: function(name, url) {
        var groups = url.match(/-([0-9]+)-([0-9]+).[a-zA-Z0-9]+$/);
        if (!groups) return;
        var width = parseInt(groups[1]), height = parseInt(groups[2]);
        
        pxl.fonts[name] = {
            url: url,
            width: width,
            height: height
        }

        css = [
            '.pxl-' + name + '-word{' +
                'float:left;' +
                'display:block;' +
                'height:' + height + 'px;' +
            '}',
            '.pxl-' + name + '-glyph{' +
                //'border:1px solid red;' +
                'float:left;' +
                'display:block;' +
                'overflow:hidden;' +
                'background-repeat:no-repeat;' +
                'background-image:url("' + url + '");' +
                'width:' + width + 'px;' +
                'height:' + height + 'px;' +
            '}'
        ];
        for (var i = 32; i < 127; i++) {
            css.push(
                '.pxl-' + name + '-glyph-' + i + '{' +
                'background-position:' + -((i - 32) * width) + 'px 0;' +
                '}');
        }
        css = css.join('\n');

        var style = document.createElement('style');
        style.setAttribute('type', 'text/css');
	if (style.styleSheet) {
	    style.styleSheet.cssText = css;
	} else {
            style.appendChild(document.createTextNode(css));
	}
        document.getElementsByTagName('head')[0].appendChild(style);
    },

    render: function(text, font) {
        var tokens = text.split(/(\s+)/);
        var words = [], linebreaks = [];
        $.each(tokens, function(n) {
            var word = String(this), glyphs = [];
            $.each(this, function(i) {
                var glyph = word.charCodeAt(i);
                if (glyph == 10 || glyph == 13) {
                    words.push(['<!-- br -->']);
                    return;
                }
                var classes = [
                    'pxl-glyph',
                    'pxl-' + font + '-glyph',
                    'pxl-' + font + '-glyph-' + glyph
                ];
                glyphs.push('<span class="' + classes.join(' ') + '"></span>');
            });
            if (!word.match(/[^\s]/g) && words.length > 0) {
                $.each(glyphs, function(i) {words[words.length - 1].push(this)});
            } else {
                words.push(glyphs);
            }
        });
        $.each(words, function(i) {
            var extra = '';
            if (words[i][0] == '<!-- br -->') {
                words[i].shift();
                extra = '<div style="clear:left;width:0;height:1px;overflow:hidden;"></div>';
            }
            words[i] = extra + (
                '<span class="pxl-word pxl-' + font + '-word" style="' +
                'width:' + (pxl.fonts[font].width * this.length) + 'px;' +
                '">' + this.join('') + '</span>');
        });
        return /*'<span class="pxl-text">' + */words.join('') /*+ '</span> '*/;
    },

    reduce_whitespace: function(element) {
        if (element.tagName == 'PRE')
            return;
        $(element).contents().each(function(i) {
            if (this.nodeType != 3)
                return;
            this.nodeValue = this.nodeValue.replace(/\s+/g, ' ');
            if (!this.previousSibling || this.previousSibling.childNodes.length == 0)
                this.nodeValue = this.nodeValue.replace(/^\s/, '');
            if (!this.nextSibling || this.nextSibling.childNodes.length == 0)
                this.nodeValue = this.nodeValue.replace(/\s$/, '');
        });
        $(element).children().each(function(i) {
            if (!($(this).hasClass('pxl')))
                pxl.reduce_whitespace(this);
        });
    },

    convert: function(element, font) {
        $(element).contents().each(function(i) {
            if (this.nodeType != 3)
                return;
            $(this).replaceWith(pxl.render(this.nodeValue, font));
        });
        $(element).children().each(function(i) {
            if (!($(this).hasClass('pxl') || this.className.match(/^pxl-?/)))
                pxl.convert(this, font);
        });
    },

    init: function() {
        $('.pxl').each(function(i) {
            pxl.reduce_whitespace(this);
        });
        $('.pxl').each(function(i) {
            var element = this;
            $.each(pxl.fonts, function(key) {
                if ($(element).hasClass(key)) {
                    pxl.convert(element, key);
                    return;
                }
            });
        });
    }
};
