(function ($) {
    /* global CodeMirror:false */
    // CodeMirror default settings
    var codeDefaults = {
        mode: "application/xml",
        lineNumbers:true,
        gutters: ['CodeMirror-linenumbers'],
        indentWithTabs:false,
        highlightSelectionMatches:true,
        indentUnit:4,
        readOnly:true,
        foldGutter: true,
        cursorBlinkRate: 0
    };

    /**
     * Turn <pre><code></code></pre> blocks in to CodeMirrors
     * @param {HTMLElement} block
     */
    function cmIfyPreCodeBlocks(block) {
        var $sample = $(block);
        var lang = $sample.attr('data-lang');
        var text = $sample.text().trim();
        var newOpts = $.extend({}, codeDefaults);

        if (text.split("\n").length <= 1) {
            newOpts.lineNumbers = false;
            newOpts.gutters = [];
        }
        newOpts.value = text;

        if (lang) {
            newOpts.mode = lang;
        }

        CodeMirror(
            function(node){
                block.parentNode.replaceChild(node, block);
            }, newOpts
        );
    }

    // A CSS class to mime-type mapping
    var classMapping = {
        java: 'text/x-java',
        javascript: 'text/javascript',
        json: 'application/json',
        properties: 'text/x-properties',
        scala: 'text/x-scala',
        soy: 'text/x-smarty',
        sh: 'text/x-sh',
        xml: 'application/xml'
    };

    /**
     * Use the classMapping to map a CSS class to a mime-type that CodeMirror will use for its highlight/code mode
     * @param {jQuery} $el
     */
    function setLanguageFromClass($el) {
        if (!$el.attr('data-lang')) {
            $el.attr('data-lang', classMapping[$el[0].className]||'');
        }
    }

    /**
     * Scroll the first editor on the page to the line retrieved from the hash
     * If there is no line-xx hash we won't attempt to scroll the editor.
     */
    function scrollFirstEditorToLineFromHash() {
        var matches = window.location.hash.match(/line-(\d+)/);
        var lineNum = matches && matches[1] && (parseInt(matches[1], 10) - 1);
        var editor;

        if (lineNum !== null && lineNum >= 0) {
            editor = $(".CodeMirror")[0].CodeMirror;
            window.scrollTo(null, editor.heightAtLine(lineNum) - 100);
            editor.addLineClass(lineNum, 'wrap', 'highlighted');
        }
    }

    $(document).ready(function () {

        $("#main-content").find('pre code').each(function(){
            setLanguageFromClass($(this));
            cmIfyPreCodeBlocks(this);
        });

        scrollFirstEditorToLineFromHash();
    });

}(jQuery));