var PrettyPrint = (function()
{
    this.styleBraces = function(markup)
    {
        var re_braces = /([{}\(\)])/g;
        return markup.replace(re_braces,"<span class=\"pp_brace\">$1</span>");
    }

    this.styleClasses = function(markup)
    {
        var re_class_words = /\b(class|extends|private|public|var|static|final)(?= )/g;
        // super and new are differnt because it will always be followed by an (
        var re_super = /\b(super|new)(?=\s*\()/g;
        return markup.replace(re_class_words,"<span class=\"pp_class\">$1</span>").
                replace(re_super,"<span class=\"pp_class\">$1</span>");
    }

    this.styleFunctions = function(markup)
    {
        var re_functions = /\b(function)(?= )/g;
        return markup.replace(re_functions,"<span class=\"pp_func\">$1</span>");
    }

    this.stylePackages = function(markup)
    {
        var re_packages = /\b(import|package)\b/g;
        return markup.replace(re_packages,"<span class=\"pp_pack\">$1</span>");
    }

    this.stripMarkupFromComment = function(markup, comment)
    {
        var stripped_comment = comment;
        while(stripped_comment.match("<span"))
        {
            stripped_comment = stripped_comment.replace(/<span class=".*?">(.*?)<\/span>/g,"$1");
        }
        return markup.replace(comment, stripped_comment);
    }

    this.styleComments = function(markup)
    {
        // go through and get rid of other markup inside of comments so
        // that comments are totally commenty
    
        var re_slashes = /([^\\])(\/\/.*)/g;
        var re_c_open = /(\/\*.*)(\*\/)?/g;
        var re_c_close = /(.*\*\/)/g;
        var re_bash = /(\#.*)/g;

        var slash_matches = markup.match(re_slashes);
        var c_open_matches = markup.match(re_c_open);
        var c_close_matches = markup.match(re_c_close);
        var bash_matches = markup.match(re_bash);

        // if no match, match array is null
        if(slash_matches)
        {
            for(var i=0; i<slash_matches.length; i++)
            {
                markup = this.stripMarkupFromComment(markup, slash_matches[i]);
            }
        }
        
        if(c_open_matches)
        {
            for(var i=0; i<c_open_matches.length; i++)
            {
                markup = this.stripMarkupFromComment(markup, c_open_matches[i]);
            }
        }

        if(c_close_matches)
        {
            for(var i=0; i<c_close_matches.length; i++)
            {
                markup = this.stripMarkupFromComment(markup, c_close_matches[i]);
            }
        }

        if(bash_matches)
        {
            for(var i=0; i<bash_matches.length; i++)
            {
                markup = this.stripMarkupFromComment(markup, bash_matches[i]);
            }
        }

        // now that internal markup is gone, mark up the comments
        
        markup = markup.replace(re_slashes,"$1<span class=\"pp_comment\">$2</span>").
                replace(re_bash,"<span class=\"pp_comment\">$1</span>").
                replace(re_c_open,"<span class=\"pp_comment\">$1").
                replace(re_c_close,"$1</span>");
    
        return markup;
    }
    
    this.styleKeywords = function(markup)
    {
        var re_keywords = /\b(if|fi|case|esac|switch|break|else|for|do|done|while|return)(?=(\s|\b|\())/g;
        return markup.replace(re_keywords,"<span class=\"pp_keys\">$1</span>");
    }

    this.styleConstants = function(markup)
    {
        // digits with dots are tricky because \b breaks after .
        var re_const = /(".*?"|'.*?'|\b0x[A-Fa-f0-9]{6}\b|\bnull\b)/g;
        var re_digit = /([\s\(,])([\d\.]+)(?=[\s,;\)])/g
        return markup.replace(re_const,"<span class=\"pp_const\">$1</span>").
                replace(re_digit,"$1<span class=\"pp_const\">$2</span>");
    }

    this.styleXML = function(markup)
    {
        var re_open = /(\&lt;[^\/\s]+)(.*?)([\/\?]?\&gt;)?/g;
        var re_close = /((\&lt;[^\s]+)?[\/\?]?\&gt;)/g;
    
        return markup.replace(re_open,"<span class=\"pp_tag\">$1</span>$2<span class=\"pp_tag\">$3</span>").
                replace(re_close,"<span class=\"pp_tag\">$1</span>");
    }

    window.onload = function (e)
    {
        var pres = document.getElementsByTagName('pre');
        for(var i=0; i<pres.length; i++)
        {
            var cur_node = pres[i];
            var markup = cur_node.innerHTML;
                
            // do constants first because it wills screw up quotes
            markup = this.styleConstants(markup);
            
            if( cur_node.className == "xml" )
            {
                markup = this.styleXML(markup);
            }
            else
            {
                markup = this.styleClasses(markup);
                markup = this.styleFunctions(markup);
                markup = this.styleKeywords(markup);
                markup = this.stylePackages(markup);
                markup = this.styleBraces(markup);
                
                // comments last to kill other markup
                markup = this.styleComments(markup);
            }

            cur_node.innerHTML = markup;
        }
    }
}());
