/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
"use strict"

/*
 * This is an Asciidoctor.js extension to process `apiref` inline macro generated by `log4j-docgen`.
 * The logic here is adapted from the `log4j-docgen-asciidoctor-extension`, in particular, `TypeLookup` and `ApirefMacro` classes.
 */

const fs = require("fs")
const { posix: path } = require("path")
const { XMLParser, XMLBuilder, XMLValidator} = require("fast-xml-parser")
const Handlebars = require("handlebars");

// Register a `replaceAll()` helper to Handlebars.
// This will be used while converting artifact information (`groupId`, `artifactId`, etc.) to a target link
// See its usage in `antora-playbook.yaml`.
Handlebars.registerHelper('replaceAll', function(input, from, to) {
   const output = input.replaceAll(from, to)
   return new Handlebars.SafeString(output)
});

function register (registry, context) {

  const { config: { attributes } } = context

  function getStringAttribute(key, defaultValue) {
    var value = attributes[key]
    if (value === undefined || (value = value.trim()).length == 0) {
      if (defaultValue === null) {
        throw new Error(`blank or missing attribute: \`key\``)
      } else {
        return defaultValue
      }
    }
    return value
  }

  function attributeName(key) {
    const attributeName = "log4j-docgen-" + key
    if (attributeName.match(/.*[^a-z0-9-]+.*/)) {
      throw new Error(`Found invalid attribute name: \`${attributeName}\`.
\`node.getDocument().getAttributes()\` lower cases all attribute names and replaces symbols with dashes.
Hence, you should use kebab-case attribute names.`)
    }
    return attributeName
  }

  /**
   * JSON paths that should be parsed into an array by `fast-xml-parser`
   */
  const descriptorXmlArrayJPaths = [
    "pluginSet.plugins.plugin",
    "pluginSet.plugins.plugin.supertypes.supertype",
    "pluginSet.abstractTypes.abstractType",
    "pluginSet.scalars.scalar"
  ]

  /**
   * XML parser for parsing descriptor XML files
   */
  const descriptorXmlParser = new XMLParser({
    ignoreAttributes: false,
    attributeNamePrefix: "",
    isArray: (name, jPath, isLeafNode, isAttribute) => {
      return descriptorXmlArrayJPaths.indexOf(jPath) !== -1
    }
  })

  /**
   * Collects the list of `.xml`-suffixed file paths by walking the directory pointed by the `log4j-docgen-descriptor-directory` attribute.
   */
  function loadDescriptorPaths() {
    const directory = getStringAttribute(attributeName("descriptor-directory"), null)
    const filePaths = []
    fs.readdirSync(directory, {withFileTypes: true, recursive: true}).forEach(entry => {
      if (entry.isFile() && !entry.name.startsWith(".") && entry.name.endsWith(".xml")) {
        const filePath = path.resolve(entry.parentPath, entry.name)
        filePaths.push(filePath)
      }
    })
    filePaths.sort()
    return filePaths
  }

  /**
   * Parses the given descriptor XML file.
   */
  function loadDescriptor(filePath) {
    const xml = fs.readFileSync(filePath, {encoding: "UTF-8"})
    const { pluginSet: pluginSet } = descriptorXmlParser.parse(xml)
    return pluginSet
  }

  /**
   * Consolidates all scalar, abstract type, and plugin information into a single dictionary keyed by the class name.
   */
  function mergeDescriptors(pluginSets, sourcedTypeByClassName) {
    pluginSets.forEach(pluginSet => {
      ["scalar", "abstractType", "plugin"].forEach(singularFieldName => {
        const pluralFieldName = singularFieldName + "s"
        if (pluralFieldName in pluginSet) {
          pluginSet[pluralFieldName][singularFieldName].forEach(type => {
            sourcedTypeByClassName[type.className] = {
              groupId: pluginSet.groupId,
              artifactId: pluginSet.artifactId,
              version: pluginSet.version,
              type: type
            }
          })
        }
      })
    })
  }

  /**
   * Enriches the given `sourcedTypeByClassName` with `supertypes` extracted from the given `pluginSets`.
   */
  function populateTypeHierarchy(pluginSets, sourcedTypeByClassName) {
    pluginSets.forEach(pluginSet => {
      if ("plugins" in pluginSet) {
        pluginSet["plugins"]["plugin"].forEach(plugin => {
          if ("supertypes" in plugin) {
            plugin["supertypes"]["supertype"].forEach(superTypeClassName => {
              if (!(superTypeClassName in sourcedTypeByClassName)) {
                sourcedTypeByClassName[superTypeClassName] = {
                  groupId: pluginSet.groupId,
                  artifactId: pluginSet.artifactId,
                  version: pluginSet.version,
                  type: {className: superTypeClassName}
                }
              }
            })
          }
        })
      }
    })
  }

  /**
   * Removes entries from the given `sourcedTypeByClassName` object whose key matches with the `log4j-docgen-type-filter-exclude-pattern` attribute.
   */
  function filterTypes(sourcedTypeByClassName) {
    const excludePattern = getStringAttribute(attributeName("type-filter-exclude-pattern"), null)
    Object.keys(sourcedTypeByClassName).forEach(className => {
      const excluded = className.match(excludePattern)
      if (excluded) {
        delete sourcedTypeByClassName[className]
      }
    })
  }

  function loadDescriptors() {
    const filePaths = loadDescriptorPaths()
    const pluginSets = filePaths.map(loadDescriptor)
    const sourcedTypeByClassName = {}
    mergeDescriptors(pluginSets, sourcedTypeByClassName)
    populateTypeHierarchy(pluginSets, sourcedTypeByClassName)
    filterTypes(sourcedTypeByClassName)
    return sourcedTypeByClassName
  }

  function createInlineApirefMacro({ file }) {

    const sourcedTypeByClassName = loadDescriptors()
    const typeTargetTemplateSource = getStringAttribute(attributeName("type-target-template"), null)
    const typeTargetTemplate = Handlebars.compile(typeTargetTemplateSource)

    return function () {
      this.process((parent, target, attributes) => {

        const methodSplitterIndex = target.indexOf("#")
        const methodProvided = methodSplitterIndex > 0
        const className = methodProvided ? target.substr(0, methodSplitterIndex) : target
        const label = "$positional" in attributes ? attributes.$positional.join(" ") : null

        // If the type is provided in descriptors
        const sourcedType = sourcedTypeByClassName[className]
        if (sourcedType) {
          const extendedAttributes = {
            type: "xref",
            target: typeTargetTemplate({sourcedType: sourcedType}),
            attributes
          }
          const effectiveLabel = label ? label : className.substr(className.lastIndexOf(".") + 1)
          return this.createInline(parent, "anchor", effectiveLabel, extendedAttributes)
        }

        // Otherwise we don't know the link
        const text = label ? `<em>${label}</em>` : `<code>${target}</code>`
        return this.createInline(parent, "quoted", text, attributes)

      })
    }

  }

  registry.inlineMacro('apiref', createInlineApirefMacro(context))

}

module.exports.register = register
