import {render} from 'posthtml-render'
import {parser} from 'posthtml-parser'
import * as djot from '@djot/djot'
import minIndent from 'min-indent'
import {resolve} from 'node:path'
import {readFileSync} from 'node:fs'
import {match} from 'posthtml/lib/api.js'

const normalize = data => {
  const indents = minIndent(data)

  // Removing indents
  if (indents !== 0) {
    const replaceRegex = new RegExp(`^[ \\t]{${indents}}`, 'gm')

    return data.replace(replaceRegex, '')
  }

  return data
}

const parse = (data, settings, html_settings, hasTag) => {
  // Parsing content
  const parsed = djot.renderHTML(djot.parse(data, settings), html_settings)

  return hasTag ? `\n${parsed}` : parsed
}

const importDjot = (src, settings) => {
  const from = resolve(settings.root, src)
  const content = readFileSync(from, settings.encoding)

  return normalize(content)
}

const plugin = options => {
  const settings = {
    root: './',
    encoding: 'utf8',
    djot: {},
    djot_html: {},
    ...options
  }

  return tree => {
    tree.match = tree.match || match
    tree.match([
      {tag: 'dj'},
      {tag: 'djot'},
      {attrs: {dj: ''}},
      {attrs: {djot: ''}}
    ], node => {
      let content = ''

      if (['dj', 'djot'].includes(node.tag)) {
        node.tag = false
      }

      if (node.attrs) {
        // Change tag
        if (node.attrs.tag) {
          node.tag = node.attrs.tag

          delete node.attrs.tag
        }

        for (const attribute of ['dj', 'djot']) {
          if (attribute in node.attrs) {
            delete node.attrs[attribute]
          }
        }

        // Import djot file if specified
        const src = node.attrs.src || false

        if (src) {
          content += importDjot(src, settings)

          if (tree.messages) {
            const from = resolve(settings.root, src)

            tree.messages.push({
              type: 'dependency',
              file: from
            })
          }

          delete node.attrs.src
        }
      }

      // Converting content to html tree
      content += normalize(render(node.content))

      // Parsing content
      const parsed = parse(content, settings.djot, settings.djot_html, node.tag)

      // Converting tree to html content
      node.content = parser(parsed)

      return node
    })

    return tree
  }
}

export default plugin
