/**
 * Simplified implementation of remark-attr that allows custom attributes on
 * nodes *inline* via the following syntax: {#some-id key="value"}. Extracting
 * them inline is slightly hackier (at least in this implementation), but it
 * makes the resulting markup valid and compatible with formatters like
 * Prettier, which do not allow additional content right below headlines.
 * Based on: https://github.com/arobase-che/remark-attr
 */

const visit = require('unist-util-visit')
const parseAttr = require('md-attr-parser')

const defaultOptions = {
    elements: ['heading'],
}

module.exports = ({ markdownAST }, userOptions = {}) => {
    const options = Object.assign({}, defaultOptions, userOptions)
    visit(markdownAST, null, node => {
        if (options.elements.includes(node.type)) {
            if (
                node.children &&
                node.children.length &&
                node.children[node.children.length - 1].type === 'text' &&
                node.children[node.children.length - 1].value
            ) {
                if (node.children.length > 1 && node.children.every(el => el.type === 'text')) {
                    // If headlines contain escaped characters, e.g.
                    // Doc.\_\_init\_\_, it will be split into several nodes
                    const mergedText = node.children.map(el => el.value).join('')
                    node.children[0].value = mergedText
                    node.children = [node.children[0]]
                }
                const lastIdx = node.children.length - 1
                const parsed = node.children[lastIdx].value.split(/\{(.*?)\}/)
                if (parsed.length >= 2 && parsed[1]) {
                    const text = parsed[0]
                    const { prop } = parseAttr(parsed[1])
                    const data = node.data || (node.data = {})
                    const hProps = data.hProperties || (data.hProperties = {})
                    node.data.hProperties = Object.assign({}, hProps, prop)
                    node.children[lastIdx].value = text
                }
            }
        }
    })
    return markdownAST
}
