export default (codemirror) => {
    (function (mod) {
        mod(codemirror)
    })(function (CodeMirror) {
        CodeMirror.defineOption('placeholder', '', function (cm, val, old) {
            var prev = old && old !== CodeMirror.Init
            if (val && !prev) {
                cm.on('blur', onBlur)
                cm.on('change', onChange)
                cm.on('swapDoc', onChange)
                onChange(cm)
            } else if (!val && prev) {
                cm.off('blur', onBlur)
                cm.off('change', onChange)
                cm.off('swapDoc', onChange)
                clearPlaceholder(cm)
                var wrapper = cm.getWrapperElement()
                wrapper.className = wrapper.className.replace(' CodeMirror-empty', '')
            }

            if (val && !cm.hasFocus()) onBlur(cm)
        })

        function clearPlaceholder (cm) {
            if (cm.state.placeholder) {
                cm.state.placeholder.parentNode.removeChild(cm.state.placeholder)
                cm.state.placeholder = null
            }
        }
        function setPlaceholder (cm) {
            clearPlaceholder(cm)
            var elt = cm.state.placeholder = document.createElement('pre')
            elt.style.cssText = 'height: 0; overflow: visible; color: #80848f;'
            elt.style.direction = cm.getOption('direction')
            elt.className = 'CodeMirror-placeholder'
            var placeHolder = cm.getOption('placeholder')
            if (typeof placeHolder === 'string') placeHolder = document.createTextNode(placeHolder)
            elt.appendChild(placeHolder)
            cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild)
        }

        function onBlur (cm) {
            if (isEmpty(cm)) setPlaceholder(cm)
        }
        function onChange (cm) {
            let wrapper = cm.getWrapperElement()
            let empty = isEmpty(cm)
            wrapper.className = wrapper.className.replace(' CodeMirror-empty', '') + (empty ? ' CodeMirror-empty' : '')

            if (empty) setPlaceholder(cm)
            else clearPlaceholder(cm)
        }

        function isEmpty (cm) {
            return (cm.lineCount() === 1) && (cm.getLine(0) === '')
        }
    })
}
