/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed 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.
 */

package com.google.devsite.renderer.converters

import com.google.devsite.DocsSummaryList
import com.google.devsite.LinkDescriptionSummaryList
import com.google.devsite.className
import com.google.devsite.components.ContextFreeComponent
import com.google.devsite.components.DescriptionComponent
import com.google.devsite.components.Link
import com.google.devsite.components.impl.DefaultAnnotatedLink
import com.google.devsite.components.impl.DefaultDescriptionComponent
import com.google.devsite.components.impl.DefaultKmpTableRowSummaryItem
import com.google.devsite.components.impl.DefaultLink
import com.google.devsite.components.impl.DefaultParameterComponent
import com.google.devsite.components.impl.DefaultPlatformComponent
import com.google.devsite.components.impl.DefaultSummaryList
import com.google.devsite.components.impl.DefaultTableRowSummaryItem
import com.google.devsite.components.impl.DefaultTableTitle
import com.google.devsite.components.impl.DefaultTypeProjectionComponent
import com.google.devsite.components.impl.DefaultUnlink
import com.google.devsite.components.impl.UndocumentedSymbolDescriptionComponent
import com.google.devsite.components.symbols.AnnotatedLink
import com.google.devsite.components.symbols.ParameterComponent
import com.google.devsite.components.symbols.TypeProjectionComponent
import com.google.devsite.components.table.KmpTableRowSummaryItem
import com.google.devsite.components.table.SummaryList
import com.google.devsite.components.table.TableRowSummaryItem
import com.google.devsite.components.table.TableTitle
import com.google.devsite.renderer.Language
import com.google.devsite.renderer.impl.DocumentablesHolder
import com.google.devsite.renderer.impl.paths.FilePathProvider
import com.google.devsite.strictSingleOrNull
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.model.Annotations
import org.jetbrains.dokka.model.Callable
import org.jetbrains.dokka.model.DClasslike
import org.jetbrains.dokka.model.DFunction
import org.jetbrains.dokka.model.DParameter
import org.jetbrains.dokka.model.DProperty
import org.jetbrains.dokka.model.DTypeAlias
import org.jetbrains.dokka.model.DTypeParameter
import org.jetbrains.dokka.model.DefinitelyNonNullable
import org.jetbrains.dokka.model.Documentable
import org.jetbrains.dokka.model.Dynamic
import org.jetbrains.dokka.model.JavaObject
import org.jetbrains.dokka.model.Nullable
import org.jetbrains.dokka.model.PrimitiveJavaType
import org.jetbrains.dokka.model.Projection
import org.jetbrains.dokka.model.Star
import org.jetbrains.dokka.model.StringValue
import org.jetbrains.dokka.model.TypeAliased
import org.jetbrains.dokka.model.TypeConstructor
import org.jetbrains.dokka.model.TypeParameter
import org.jetbrains.dokka.model.UnresolvedBound
import org.jetbrains.dokka.model.Variance
import org.jetbrains.dokka.model.Void
import org.jetbrains.dokka.model.WithChildren
import org.jetbrains.dokka.model.WithConstructors
import org.jetbrains.dokka.model.WithGenerics
import org.jetbrains.dokka.model.WithSources
import org.jetbrains.dokka.model.doc.Author
import org.jetbrains.dokka.model.doc.Constructor
import org.jetbrains.dokka.model.doc.CustomTagWrapper
import org.jetbrains.dokka.model.doc.Deprecated
import org.jetbrains.dokka.model.doc.Description
import org.jetbrains.dokka.model.doc.DocTag
import org.jetbrains.dokka.model.doc.DocumentationLink
import org.jetbrains.dokka.model.doc.NamedTagWrapper
import org.jetbrains.dokka.model.doc.P
import org.jetbrains.dokka.model.doc.Param
import org.jetbrains.dokka.model.doc.Pre
import org.jetbrains.dokka.model.doc.Property
import org.jetbrains.dokka.model.doc.Receiver
import org.jetbrains.dokka.model.doc.Return
import org.jetbrains.dokka.model.doc.Sample
import org.jetbrains.dokka.model.doc.See
import org.jetbrains.dokka.model.doc.Since
import org.jetbrains.dokka.model.doc.Suppress
import org.jetbrains.dokka.model.doc.TagWrapper
import org.jetbrains.dokka.model.doc.Text
import org.jetbrains.dokka.model.doc.Throws
import org.jetbrains.dokka.model.doc.Version
import java.io.File

/** Extracts the handwritten documentation from documentables into the correct components. */
internal class DocTagConverter(
    private val displayLanguage: Language,
    private val pathProvider: FilePathProvider,
    private val docsHolder: DocumentablesHolder,
    private val paramConverter: ParameterDocumentableConverter,
    private val annotationConverter: AnnotationDocumentableConverter,
) {
    // We currently assume all sample are in the common sourceSet. TODO KMP samples b/181224204
    // private val analysisMap = runBlocking { docsHolder.analysisMap() }

    /**
     * @param documentable the documentable we are getting the documentation of
     * @param deprecationAnnotation the @Deprecated annotation. Is a parameter because for e.g.
     * getters, the annotation will be propagated manually from some higher element, so we can't
     * just use documentable.deprecationAnnotation() in such a case.
     * @return the in-source hand-written element documentation
     */
    fun summaryDescription(
        documentable: Documentable,
        deprecationAnnotation: Annotations.Annotation? = documentable.deprecationAnnotation(),
    ): DescriptionComponent {
        return deprecationComponent(documentable, summary = true, deprecationAnnotation)
            ?: documentable.getDescription(summary = true)
    }

    /** metadata() can either take a WithSources Documentable, OR an isFromJava boolean */
    fun <T> metadata(
        documentable: T,
        returnType: TypeProjectionComponent? = null,
        paramNames: List<String> = emptyList(),
        deprecationAnnotation: Annotations.Annotation? = documentable.deprecationAnnotation(),
    ) where T : Documentable, T : WithSources =
        metadataImpl(documentable, returnType, paramNames, deprecationAnnotation)

    fun metadata(
        documentable: Documentable,
        returnType: TypeProjectionComponent? = null,
        paramNames: List<String> = emptyList(),
        deprecationAnnotation: Annotations.Annotation? = documentable.deprecationAnnotation(),
        isFromJava: Boolean,
    ) = metadataImpl(documentable, returnType, paramNames, deprecationAnnotation, isFromJava)

    /**
     * Returns a breakdown of the different metadata as a deprecation warning, description, and then
     * separate summaries. Examples include the list of parameters, return type, see also, throws,
     * etc.
     */
    private fun metadataImpl(
        documentable: Documentable,
        returnType: TypeProjectionComponent? = null,
        paramNames: List<String> = emptyList(),
        deprecationAnnotation: Annotations.Annotation? = documentable.deprecationAnnotation(),
        isFromJavaParam: Boolean? = null,
    ): List<ContextFreeComponent> {
        val isFromJava = if (isFromJavaParam != null) {
            isFromJavaParam
        } else {
            assert(documentable is WithSources)
            (documentable as WithSources).isFromJava()
        }
        val description = documentable.getDescription(summary = false)
        val deprecation = deprecationComponent(documentable, summary = false, deprecationAnnotation)
        val receiverParam = documentable.find<Receiver>()?.let {
            Param(it.root, "receiver")
        }
        val generics = if (documentable is WithGenerics) documentable.generics else emptyList()
        // Filter out tags which should instead be put into the Description, which is handled in the
        // getDescription method.
        val metadataTags = (listOfNotNull(receiverParam) + documentable.tags())
            .filter { !it.belongsInDescriptionOf(documentable) }
        val tagsByType = metadataTags.sortedWith(tagOrder(paramNames)).groupBy { it.javaClass }
        val tables = tagsByType.mapNotNull { (_, rawTags) ->
            var tags = handleUpstreamTagDuplication(documentable, rawTags, generics)
            if (tags.isEmpty()) return@mapNotNull null
            val firstTag = tags.first()
            if (documentable is DFunction && firstTag is Param) {
                val propertyClass = Property::class.java as Class<*>
                tags = tags + tagsByType[propertyClass].orEmpty()
            }
            // We know all the elements in `tags` will be of the same type, so we pick an arbitrary
            // one to do the switching and then cast the list to its type.
            @kotlin.Suppress("UNCHECKED_CAST")
            try {
                when (firstTag) {
                    is Param -> params(
                        tags as List<NamedTagWrapper>,
                        generics,
                        documentable,
                        isFromJava,
                        documentable.getExpectOrCommonSourceSet(),
                    )
                    is Return -> returnType(tags as List<Return>, checkNotNull(returnType))
                    is Throws -> throws(tags as List<Throws>, documentable)
                    is See -> see(tags as List<See>, documentable)
                    is Sample -> null // Samples are handled in the description
                    is Property ->
                        throw RuntimeException("Should have been consumed in description!")
                    is CustomTagWrapper -> docsHolder.printWarningFor(
                        "unrecognized javadoc tag @",
                        documentable,
                        brokenDocTag = firstTag,
                    ).let { null }
                    is Since -> docsHolder.printWarningFor(
                        "unsupported javadoc tag @",
                        documentable,
                        brokenDocTag = firstTag,
                        additionalContext = ". Instead, autogenerate per go/dackka#api-since.",
                    ).let { null }
                    is Constructor -> null // TODO("b/179999964: constructor")
                    is Description, is Deprecated -> null // Documented separately in getDescription
                    is Receiver -> null // gets merged with @params
                    is Suppress -> throw RuntimeException(
                        "Reaching the documentation generation step on a suppressed member should" +
                            "be impossible! If you see this, file a bug on dackka. $documentable",
                    )
                    // These aren't tags we believe it is necessary to support
                    is Version, is Author -> null
                }
            } catch (e: Exception) {
                throw RuntimeException(
                    "Exception thrown while handling ${firstTag.className} tags $tags.",
                    e,
                )
            }
        }

        return listOfNotNull(deprecation, description, *tables.toTypedArray())
    }

    // Turn both "E" and "<E>" to "E"
    private fun ungenerify(name: String): String {
        if (name.startsWith('<') && name.endsWith('>')) return name.drop(1).dropLast(1)
        return name
    }
    private fun TagWrapper.name() = ungenerify((this as NamedTagWrapper).name)
    private fun List<TagWrapper>.names() = this.map { it.name() }

    /* Tags, in particular for property parameters, are propagated multiple times in upstream.
     * For example, @param t t_doc class Foo(val t) has Parameter(t, t_doc) duplicated many times.
     * On the class itself, on each property parameter of that class, and on the constructor.
     * This function filters out inappropriately propagated docs, and enforces that documentation
     * applies only to existing properties and parameters.
     */
    private fun handleUpstreamTagDuplication(
        documentable: Documentable,
        tags: List<TagWrapper>,
        generics: List<DTypeParameter>,
    ): List<TagWrapper> {
        if (tags.first() is Param) {
            // This one is very strange, and I haven't been able to reproduce it in unit tests
            // A generic called "ToValue" is instead registered as being named "V"
            // TODO: Fix
            if (tags.names() == listOf("ToValue", "function") && generics.single().name == "V") {
                return tags.filter { (it as Param).name == "function" }
            }

            // Handle parameter properties, e.g. class AClass<Gen>(val propParam)
            when (documentable) {
                // doc is DClasslike. DClasslike's only valid @params are type params
                is DClasslike -> {
                    val genericNames = generics.map { it.name }
                    val (forGenerics, otherAtParams) = tags.partition { it.name() in genericNames }
                    if (otherAtParams.isEmpty()) return forGenerics
                    // Enforce that the propagated documentation makes sense somewhere. Specifically
                    // documentation primarily aimed at a constructor may wind up on the DClass
                    // if the parameter being documented is a primary constructor property parameter
                    val constructorParamNames = (documentable as? WithConstructors)?.constructors
                        ?.map { constructor -> constructor.parameters.map { it.name!! } }?.flatten()
                        .orEmpty()
                    val otherNames =
                        (documentable.properties.map { it.name } + constructorParamNames)
                    val (validTags, badTags) = otherAtParams.partition { it.name() in otherNames }
                    badTags.forEach {
                        docsHolder.printWarningFor(
                            "Unable to find reference @",
                            documentable,
                            brokenDocTag = it,
                            additionalContext =
                            ". Are you trying to refer to something not visible to users?",
                        )
                    }
                    // Use only docs for type parameters in the parameter documentation table
                    return forGenerics
                }
                // doc is Property. It is possible that a parameter property is documented on the
                // class as @param. That doc is used as though it were @property. Handled there.
                // Properties can also have @param documentation for type parameters
                is DProperty -> {
                    val genericNames = generics.map { it.name }
                    val (forGenericsOrThis, badTags) = tags
                        .partition { it.name() in genericNames || it.name() == documentable.name }
                    badTags.forEach {
                        docsHolder.printWarningFor(
                            "Unable to find reference @",
                            documentable,
                            brokenDocTag = it,
                            additionalContext =
                            ". Are you trying to refer to something not visible to users?",
                        )
                    }
                    return forGenericsOrThis
                }
                is DFunction -> {}
                else ->
                    throw RuntimeException("Can't apply @param to a ${documentable.className}")
            }
        } else if (tags.first() is Property) {
            // A DClasslike with @property applying to property parameters may have Parameter tags
            // In such a case, none of these tags should become docs *on the DClasslike itself*
            return when (documentable) {
                is DClasslike -> {
                    val propertyNames = documentable.properties.map { it.name }
                    tags.filter { it.name() !in propertyNames }.forEach {
                        docsHolder.printWarningFor(
                            "Unable to find reference @",
                            documentable,
                            brokenDocTag = it,
                        )
                    }
                    emptyList()
                }

                is DParameter, is DProperty -> tags
                else ->
                    throw RuntimeException("Can't apply @property to a ${documentable.className}")
            }
        }
        return tags
    }

    private fun params(
        tags: List<NamedTagWrapper>,
        dGenerics: List<DTypeParameter>,
        documentable: Documentable,
        isFromJava: Boolean,
        sourceSet: DokkaConfiguration.DokkaSourceSet,
    ): DocsSummaryList {
        val tagged = tags.map { it.name() }.toSet()

        // @param can refer to parameters, lambda parameters, type parameters, or receivers.
        val allOptions = mutableMapOf<String, ParameterComponent>()
        if (documentable is DFunction) {
            allOptions.putAll(
                documentable.parameters.mapNotNull {
                    val name = it.name!!
                    if (!tagged.contains(name)) {
                        // Synthetic receiver params don't need @param documentation
                        if (name == "receiver") return@mapNotNull null
                        docsHolder.printWarningFor(
                            "Missing @param tag for parameter `$name`",
                            documentable,
                        )
                    }
                    name to paramConverter.componentForParameter(
                        param = it,
                        isSummary = false,
                        isFromJava = isFromJava,
                        parent = documentable,
                    )
                },
            )
            allOptions.putAll(
                recursivelyGetLambdaParamNames(documentable.parameters.map { it.type }).map {
                    (it.presentableName ?: "") to paramConverter
                        .componentForLambdaParameter(it, isFromJava, sourceSet)
                },
            )
        }
        allOptions.putAll(
            dGenerics.map {
                it.name to paramConverter.componentForTypeParameter(it, isFromJava)
            },
        )
        if (documentable is Callable && documentable.receiver != null) {
            allOptions[documentable.receiver!!.name ?: "receiver"] =
                paramConverter.componentForParameter(
                    param = documentable.receiver!!,
                    isSummary = false,
                    isFromJava = isFromJava,
                    parent = documentable,
                )
        }
        val params = tags.map { tag ->
            if (allOptions[tag.name()] == null) {
                throw RuntimeException(
                    "Unable to find what is referred to by \"@param " +
                        "${tag.name()}\" in ${documentable.className} " +
                        "${documentable.name}, with contents: ${tag.text()}",
                )
            }
            val title = allOptions[tag.name()]!!
            DefaultTableRowSummaryItem(
                TableRowSummaryItem.Params(
                    title = title,
                    description = description(tag),
                ),
            )
        }

        return DefaultSummaryList(
            SummaryList.Params(
                header = DefaultTableTitle(TableTitle.Params("Parameters")),
                items = params,
            ),
        )
    }

    /** For example, "a" and "b" in `fun foo((a: (b: String) -> int)) -> Unit)` */
    private fun recursivelyGetLambdaParamNames(
        argumentTypes: List<Projection>,
    ): List<TypeConstructor> {
        val result = mutableListOf<TypeConstructor>()
        for (argumentType in argumentTypes) {
            when (argumentType) {
                is TypeConstructor -> {
                    if (argumentType.presentableName != null) result += argumentType
                    result += recursivelyGetLambdaParamNames(argumentType.projections)
                }
                is Variance<*> -> {
                    result += recursivelyGetLambdaParamNames(listOf(argumentType.inner))
                }
                is Nullable -> {
                    result += recursivelyGetLambdaParamNames(listOf(argumentType.inner))
                }
                is DefinitelyNonNullable -> {
                    result += recursivelyGetLambdaParamNames(listOf(argumentType.inner))
                }
                is TypeParameter -> {
                    /* Type parameters can't be lambdas, and are fully squashed to strings. */
                }
                is TypeAliased -> { // No clear way to decide which
                    result += recursivelyGetLambdaParamNames(
                        setOf(argumentType.inner, argumentType.typeAlias).toList(),
                    )
                }
                is PrimitiveJavaType, is JavaObject, Void, Dynamic, Star -> { /* Do nothing */ }
                is UnresolvedBound -> { /* Nothing we can do. We warn elsewhere for this case. */ }
            }
        }
        return result
    }

    private fun returnType(tags: List<Return>, returnType: TypeProjectionComponent):
        SummaryList<TableRowSummaryItem<TypeProjectionComponent, DescriptionComponent>> {
        val params = tags.map { tag ->
            DefaultTableRowSummaryItem(
                TableRowSummaryItem.Params(
                    title = returnType,
                    description = description(tag),
                ),
            )
        }

        return DefaultSummaryList(
            SummaryList.Params(
                header = DefaultTableTitle(TableTitle.Params("Returns")),
                items = params,
            ),
        )
    }

    private fun throws(tags: List<Throws>, parent: Documentable): DocsSummaryList {
        val params = tags.map { tag ->
            DefaultTableRowSummaryItem(
                TableRowSummaryItem.Params(
                    title = throwsToParameterComponent(tag, parent),
                    description = description(tag),
                ),
            )
        }

        return DefaultSummaryList(
            SummaryList.Params(
                header = DefaultTableTitle(TableTitle.Params("Throws")),
                items = params,
            ),
        )
    }

    private fun String.firstWord() = substring(0, indexOfFirst { it == ' ' })

    private fun throwsToParameterComponent(
        throws: Throws,
        parent: Documentable,
    ): ParameterComponent {
        val name = throws.name
        var dri: DRI? = throws.exceptionAddress
        if (throws.name in listOf("a", "an")) {
            throw RuntimeException(
                "Do not use '${throws.name}' before the exception type in an @throws statement. " +
                    "This is against jdoc spec. Your exception is not being linked and looks bad",
            )
        } else if ("{@link" in name) {
            throw RuntimeException(
                "Do not {@link the exception type in an @throws statement. @throws state" +
                    "ments are automatically linked. Manually java-linking them is against jdoc s" +
                    "pec, and breaks linking behavior causing them to actually *not* be linked.",
            )
        } else if (throws.exceptionAddress == null) {
            docsHolder.printWarningFor(
                "Link does not resolve for @",
                parent,
                brokenDocTag = throws,
                additionalContext = ". Is it from a package that the containing file does not " +
                    "import? Are docs inherited by an un-documented override function, but the " +
                    "exception class is not in scope in the inheriting class? The general fix for" +
                    " these is to fully qualify the exception name, e.g. " +
                    "`@throws java.io.IOException under some conditions`.",
            )
            dri = null
        }
        val link = if (dri == null) {
            DefaultLink(Link.Params(name, url = ""))
        } else pathProvider.linkForReference(throws.exceptionAddress!!, name)

        return DefaultParameterComponent(
            ParameterComponent.Params(
                name = "",
                type = DefaultTypeProjectionComponent(
                    TypeProjectionComponent.Params(
                        type = link,
                        nullability = Nullability.DONT_CARE,
                        displayLanguage = displayLanguage,
                    ),
                ),
                displayLanguage = displayLanguage,
            ),
        )
    }

    private fun see(tags: List<See>, parent: Documentable): LinkDescriptionSummaryList {
        val params = tags.map { tag ->
            DefaultTableRowSummaryItem(
                TableRowSummaryItem.Params(
                    title = tag.toLink(parent),
                    description = description(tag),
                ),
            )
        }

        return DefaultSummaryList(
            SummaryList.Params(
                header = DefaultTableTitle(TableTitle.Params("See also")),
                items = params,
            ),
        )
    }

    /**
     * Gets a Description for the Documentable, or returns UndocumentedSymbolDescription()
     * Has special handling to inject @property documentation as a description, if it exists
     * Also applies to @param documentation that should become a description, i.e. property params
     */
    private fun Documentable.getDescription(summary: Boolean): DescriptionComponent {
        val components = mutableListOf<DocTag>()
        tags().forEach {
            when (it) {
                is Sample -> {
                    val dri = it.name
                    // val sourceSet = this.getExpectOrCommonSourceSet()
                    /* val analysisEnvironment = analysisMap[sourceSet]!!
                    val sample = try {
                        analysisEnvironment
                            .resolveSample(sourceSet, dri)!!
                    } catch (e: NullPointerException) {
                        throw RuntimeException("Unable to resolve sample $dri!")
                    }*/
                    // TODO(KMP) we currently have no plan to provide KMP samples b/181224204
                    // As such, we currently assume that all samples are in common
                    val sample = docsHolder.sampleAnalysisEnvironment
                        .resolveSample(docsHolder.commonSourceSet, dri)!!
                    val imports = processImports(sample)

                    components.add(
                        Pre(
                            params = mapOf("class" to "prettyprint lang-kotlin"),
                            children = listOf(Text(imports + sample.body)),
                        ),
                    )
                    components.addAll(it.children)
                }
                is Description, is NamedTagWrapper -> {
                    if (!it.belongsInDescriptionOf(this)) return@forEach
                    it.children.forEach { child ->
                        try {
                            recursivelyConsiderPsAndTextsForJavaSamples(
                                child,
                                components,
                                this.getExpectOrCommonSourceSet().samples,
                            )
                        } catch (e: Exception) {
                            throw RuntimeException(
                                "Error when resolving samples when processing $name",
                                e,
                            )
                        }
                    }
                }
                is Author, is Version -> {} // These are not supported
                is Return, is Receiver, is Constructor -> {} // These become tables in metadata()
                is Deprecated, is Suppress, is Since -> {} // These are handled elsewhere
            }
        }
        if (components.isEmpty()) return UndocumentedSymbolDescriptionComponent
        return description(components, summary, null)
    }

    /**
     * Tags with the same name as the documentable should generally go in the description component,
     * but sometimes the tag refers to something else with the same name, like a parameter that has
     * the same name as its function.
     */
    private fun TagWrapper.belongsInDescriptionOf(documentable: Documentable): Boolean {
        if (this is Description) return true
        if (this !is NamedTagWrapper) return false
        return when (this) {
            is Param, is Property -> (documentable is DParameter || documentable is DProperty) &&
                (this.name == documentable.name)
            is Throws, is See -> false
            else -> true
        }
    }

    /** annotation-sampled and SampledAnnotationDetector */
    private fun DocTag.explicitlyBanLookingForSamples() =
        "Functions referenced with @sample are annotated with @Sampled" in text() ||
            "Denotes that the annotated function is considered a sample function" in text() ||
            "that functions referred to from KDoc with a @sample tag are annotated" in text()

    private fun recursivelyConsiderPsAndTextsForJavaSamples(
        root: DocTag,
        components: MutableList<DocTag>,
        samples: Set<File>,
    ) {
        if ("@sample" !in root.text() || root.explicitlyBanLookingForSamples()) {
            components.add(root)
            return
        }
        when (root) {
            is Text -> {
                val parts = root.body.split("{", "}")
                for (part in parts) {
                    if ("@sample" !in part) {
                        if (part.isNotBlank()) components.add(Text(part.trim()))
                    } else components.add(convertTextToJavadocSample(Text(part.trim()), samples))
                }
            }
            is P -> {
                for (child in root.children) {
                    recursivelyConsiderPsAndTextsForJavaSamples(child, components, samples)
                }
            }
            // Having non-text components on the same line as a samples is not supported
            else -> throw RuntimeException("considered invalid type ${root.className} for sample")
        }
    }

    private fun WithChildren<DocTag>.text(): String {
        return if (this is Text) this.body else children.joinToString(" ") { it.text() }
    }

    private fun description(
        soleComponent: TagWrapper,
        summary: Boolean = false,
        deprecation: String? = null,
    ): DescriptionComponent {
        return description(soleComponent.children, summary, deprecation)
    }

    private fun description(
        components: List<DocTag> = emptyList(),
        summary: Boolean = false,
        deprecation: String? = null,
    ): DescriptionComponent {
        return DefaultDescriptionComponent(
            DescriptionComponent.Params(
                pathProvider,
                components,
                summary,
                deprecation,
                docsHolder,
            ),
        )
    }

    /** Returns the component for a deprecation. */
    private fun deprecationComponent(
        documentable: Documentable,
        summary: Boolean,
        deprecationAnnotation: Annotations.Annotation?,
    ): DescriptionComponent? {
        val deprecation = findDeprecation(documentable, deprecationAnnotation) ?: return null
        return description(deprecation.children, summary, documentable.deprecationText())
    }

    /**
     * Finds either the javadoc @deprecated tag or the Kotlin @Deprecated annotation [TagWrapper].
     */
    private fun findDeprecation(
        documentable: Documentable,
        deprecationAnnotation: Annotations.Annotation?,
    ): Deprecated? {
        val javadocDeprecation = documentable.find<Deprecated>()
        if (javadocDeprecation != null) {
            // Prefer javadoc deprecation messages since they allow formatting
            return javadocDeprecation
        }

        val annotationDeprecationMessage =
            (deprecationAnnotation?.params?.get("message") as? StringValue)?.value ?: return null
        // Dokka makes message="foo" show up as "\"foo\"" since you typically want to show quotes
        // when rendering an annotation. Remove those outer quotes.
        val message = annotationDeprecationMessage.removeSurrounding("\"")

        return Deprecated(P(children = listOf(Text(message))))
    }

    private fun Documentable.deprecationText() =
        "This ${this.stringForType(displayLanguage)} is deprecated."

    /** Retrieves the doc tags of type [T]. */
    private inline fun <reified T> Documentable.find() =
        tags().filterIsInstance<T>().strictSingleOrNull()

    /**
     * @return the doc tags (aka human-written javadoc or kdoc) associated with this documentable
     */
    private fun Documentable.tags() = documentation[getExpectOrCommonSourceSet()]?.children
        ?: emptyList()

    private fun tagOrder(paramNames: List<String>) = compareBy<TagWrapper> { tag ->
        when (tag) {
            is Deprecated -> 0
            is Description -> 1
            is Return -> 2
            is Constructor -> 3
            is Property -> 4
            is Receiver -> 5
            is Param -> 6
            is Throws -> 7
            is See -> 8
            is Sample -> 9
            is Since -> 10
            is Version -> 11
            is Author -> 12
            is Suppress -> 13
            is CustomTagWrapper -> 14
        }
    }.thenBy { tag ->
        when (tag) {
            is Param -> paramNames.indexOf(tag.name)
            else -> -1
        }
    }

    /**
     * Extract the see tag's reference into a link.
     *
     * This one is painful. An address is only sometimes there, other times there's a docs link
     * nested somewhere in the tree, and as a last resort the name is always present with whatever
     * a developer writes which could either be a fully qualified reference or just the URL
     * fragment.
     */
    private fun See.toLink(parent: Documentable): Link {
        val address = address
        if (address != null) {
            return pathProvider.linkForReference(address)
        }
        val docsLink = root.explodedChildren.filterIsInstance<DocumentationLink>().singleOrNull()
        if (docsLink != null) {
            return pathProvider.linkForReference(docsLink.dri)
        }

        // TODO(b/167437580): figure out how to reliably parse links
        val segments = name.split("#")
        return if (segments.size == 1) {
            val (packageName, typeName) = typeToPackageNameAndType(segments.single())
            if (typeName.isEmpty()) {
                var additionalContext = ""
                // Maybe the link is `package.Class.aFunction` instead of `package.Class#aFunction`?
                val last = name.substringAfterLast(".")
                val rest = name.substringBeforeLast(".")
                if (last.firstOrNull()?.isLowerCase() == true && rest.any { it.isUpperCase() }) {
                    additionalContext = ". Did you mean $rest#$last?"
                    val (packageN, typeN) = typeToPackageNameAndType(rest)
                    val url = pathProvider.forType(packageN, typeN)
                    DefaultLink(Link.Params(typeN, "$url#$last"))
                }
                docsHolder.printWarningFor(
                    "Failed to resolve ",
                    parent,
                    brokenDocTag = this,
                    additionalContext = additionalContext,
                )
                DefaultLink(Link.Params(name, url = ""))
            } else if (packageName.isEmpty()) {
                // This is a same-package type link, though we sadly can't prove it's correct
                pathProvider.linkForReference(DRI("", typeName))
            } else {
                pathProvider.linkForReference(DRI(packageName, typeName))
            }
        } else if (segments.size == 2) {
            val (type, anchor) = segments
            if (type.isEmpty()) {
                // Self link
                DefaultLink(Link.Params(anchor, anchor))
            } else {
                // Assume link with anchor
                val (packageName, typeName) = typeToPackageNameAndType(type)
                val url = pathProvider.forType(packageName, typeName)
                DefaultLink(Link.Params(typeName, "$url#$anchor"))
            }
        } else {
            throw RuntimeException("Could not understand path: $name")
        }
    }

    /** Horrible guess-work to try and extract the package and type names. */
    private fun typeToPackageNameAndType(full: String): Pair<String, String> {
        val parts = full.split(".")

        if (parts.size == 1) return "" to full

        val packageName = parts.takeWhile { it.all(Char::isLowerCase) }.joinToString(".")
        val typeName = parts.takeLastWhile {
            if (it.isEmpty()) {
                throw RuntimeException("empty element in TTPNAT. Full: $full")
            } else it.first().isUpperCase()
        }.joinToString(".")
        return packageName to typeName
    }

    internal fun docsToSummaryDefault(documentables: List<Documentable>) =
        docsToSummary(documentables, false)

    /**
     * Converts a generic List<Documentable> to a SummaryList.
     * Does nothing clever; only converts Documentables to links (by default with annotations)
     */
    private fun docsToSummary(
        documentables: List<Documentable>,
        showAnnotations: Boolean,
    ) = DefaultSummaryList(
        SummaryList.Params(
            items = documentables
                .map { summaryForDocumentable(it, showAnnotations) },
        ),
    )

    /**
     * Converts generic Documentables to TableRowSummaryItems, as simple maybe-annotated links
     * This is used for mini-signatures, e.g. nested types list, subclasses list, package summary
     */
    internal fun summaryForDocumentable(
        documentable: Documentable,
        showAnnotations: Boolean = false,
    ): TableRowSummaryItem<Link, DescriptionComponent> {
        val link = if (documentable is DTypeAlias) {
            // typealiases have no pages
            DefaultUnlink(Link.Params(documentable.name, ""))
        } else pathProvider.linkForReference(documentable.dri)
        val maybeAnnotatedLink = if (showAnnotations) {
            DefaultAnnotatedLink(
                AnnotatedLink.Params(
                    annotations = annotationConverter.annotationComponents(
                        documentable.annotations(documentable.getExpectOrCommonSourceSet()),
                        nullability = Nullability.DONT_CARE, // Not useful for these cases
                    ),
                    link = link,
                ),
            )
        } else {
            link
        }
        return DefaultTableRowSummaryItem(
            TableRowSummaryItem.Params(
                title = maybeAnnotatedLink,
                description = summaryDescription(
                    documentable,
                    documentable.deprecationAnnotation(),
                ),
            ),
        )
    }

    /**
     * Converts a generic List<Documentable> to a SummaryList.
     * Does nothing clever; only converts Documentables to links (by default with annotations)
     */
    internal fun docsToSummaryKmp(
        documentables: List<Documentable>,
    ) = DefaultSummaryList(
        SummaryList.Params(
            items = documentables
                .map { summaryForDocumentableKmp(it) },
        ),
    )

    /**
     * Converts generic Documentables to TableRowSummaryItems, as simple maybe-annotated links
     * This is used for mini-signatures, e.g. nested types list, subclasses list, package summary
     */
    private fun summaryForDocumentableKmp(
        documentable: Documentable,
    ): TableRowSummaryItem<Link, DescriptionComponent> {
        return DefaultKmpTableRowSummaryItem(
            KmpTableRowSummaryItem.Params(
                title = pathProvider.linkForReference(documentable.dri),
                description = summaryDescription(documentable),
                platforms = DefaultPlatformComponent(documentable.sourceSets),
            ),
        )
    }
}
