package org.jetbrains.dokka.javadoc

import com.sun.javadoc.*
import org.jetbrains.dokka.*
import java.lang.reflect.Modifier
import java.util.*
import kotlin.reflect.KClass

private interface HasModule {
    val module: ModuleNodeAdapter
}

private interface HasDocumentationNode {
    val node: DocumentationNode
}

open class DocumentationNodeBareAdapter(override val node: DocumentationNode) : Doc, HasDocumentationNode {
    private var rawCommentText_: String? = null

    override fun name(): String = node.name
    override fun position(): SourcePosition? = SourcePositionAdapter(node)

    override fun inlineTags(): Array<out Tag>? = emptyArray()
    override fun firstSentenceTags(): Array<out Tag>? = emptyArray()
    override fun tags(): Array<out Tag> = emptyArray()
    override fun tags(tagname: String?): Array<out Tag>? = tags().filter { it.kind() == tagname || it.kind() == "@$tagname" }.toTypedArray()
    override fun seeTags(): Array<out SeeTag>? = tags().filterIsInstance<SeeTag>().toTypedArray()
    override fun commentText(): String = ""

    override fun setRawCommentText(rawDocumentation: String?) {
        rawCommentText_ = rawDocumentation ?: ""
    }

    override fun getRawCommentText(): String = rawCommentText_ ?: ""

    override fun isError(): Boolean = false
    override fun isException(): Boolean = node.kind == NodeKind.Exception
    override fun isEnumConstant(): Boolean = node.kind == NodeKind.EnumItem
    override fun isEnum(): Boolean = node.kind == NodeKind.Enum
    override fun isMethod(): Boolean = node.kind == NodeKind.Function
    override fun isInterface(): Boolean = node.kind == NodeKind.Interface
    override fun isField(): Boolean = node.kind == NodeKind.Field
    override fun isClass(): Boolean = node.kind == NodeKind.Class
    override fun isAnnotationType(): Boolean = node.kind == NodeKind.AnnotationClass
    override fun isConstructor(): Boolean = node.kind == NodeKind.Constructor
    override fun isOrdinaryClass(): Boolean = node.kind == NodeKind.Class
    override fun isAnnotationTypeElement(): Boolean = node.kind == NodeKind.Annotation

    override fun compareTo(other: Any?): Int = when (other) {
        !is DocumentationNodeAdapter -> 1
        else -> node.name.compareTo(other.node.name)
    }

    override fun equals(other: Any?): Boolean = node.qualifiedName() == (other as? DocumentationNodeAdapter)?.node?.qualifiedName()
    override fun hashCode(): Int = node.name.hashCode()

    override fun isIncluded(): Boolean = node.kind != NodeKind.ExternalClass
}


// TODO think of source position instead of null
// TODO tags
open class DocumentationNodeAdapter(override val module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeBareAdapter(node), HasModule {
    override fun inlineTags(): Array<out Tag> = buildInlineTags(module, this, node.content).toTypedArray()
    override fun firstSentenceTags(): Array<out Tag> = buildInlineTags(module, this, node.summary).toTypedArray()

    override fun tags(): Array<out Tag> {
        val result = ArrayList<Tag>(buildInlineTags(module, this, node.content))
        node.content.sections.flatMapTo(result) {
            when (it.tag) {
                ContentTags.SeeAlso -> buildInlineTags(module, this, it)
                else -> emptyList<Tag>()
            }
        }

        node.deprecation?.let {
            val content = it.content.asText()
            result.add(TagImpl(this, "deprecated", content ?: ""))
        }

        return result.toTypedArray()
    }
}

// should be extension property but can't because of KT-8745
private fun <T> nodeAnnotations(self: T): List<AnnotationDescAdapter> where T : HasModule, T : HasDocumentationNode
    = self.node.annotations.map { AnnotationDescAdapter(self.module, it) }

private fun DocumentationNode.hasAnnotation(klass: KClass<*>) = klass.qualifiedName in annotations.map { it.qualifiedName() }
private fun DocumentationNode.hasModifier(name: String) = details(NodeKind.Modifier).any { it.name == name }


class PackageAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc {
    private val allClasses = listOf(node).collectAllTypesRecursively()

    override fun findClass(className: String?): ClassDoc? =
            allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) }

    override fun annotationTypes(): Array<out AnnotationTypeDoc> = emptyArray()
    override fun annotations(): Array<out AnnotationDesc> = node.members(NodeKind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray()
    override fun exceptions(): Array<out ClassDoc> = node.members(NodeKind.Exception).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
    override fun ordinaryClasses(): Array<out ClassDoc> = node.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
    override fun interfaces(): Array<out ClassDoc> = node.members(NodeKind.Interface).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
    override fun errors(): Array<out ClassDoc> = emptyArray()
    override fun enums(): Array<out ClassDoc> = node.members(NodeKind.Enum).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
    override fun allClasses(filter: Boolean): Array<out ClassDoc> = allClasses.values.map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
    override fun allClasses(): Array<out ClassDoc> = allClasses(true)

    override fun isIncluded(): Boolean = node.name in module.allPackages
}

class AnnotationTypeDocAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ClassDocumentationNodeAdapter(module, node), AnnotationTypeDoc {
    override fun elements(): Array<out AnnotationTypeElementDoc>? = emptyArray() // TODO
}

class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : AnnotationDesc {
    override fun annotationType(): AnnotationTypeDoc? = AnnotationTypeDocAdapter(module, node) // TODO ?????
    override fun isSynthesized(): Boolean = false
    override fun elementValues(): Array<out AnnotationDesc.ElementValuePair>? = emptyArray() // TODO
}

open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc {
    override fun isPublic(): Boolean = true
    override fun isPackagePrivate(): Boolean = false
    override fun isStatic(): Boolean = node.hasModifier("static")
    override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0
    override fun qualifiedName(): String? = node.qualifiedName()
    override fun annotations(): Array<out AnnotationDesc>? = nodeAnnotations(this).toTypedArray()
    override fun modifiers(): String? = "public ${if (isStatic) "static" else ""}".trim()
    override fun isProtected(): Boolean = false

    override fun isFinal(): Boolean = node.hasModifier("final")

    override fun containingPackage(): PackageDoc? {
        if (node.kind == NodeKind.Type) {
            return null
        }

        var owner: DocumentationNode? = node
        while (owner != null) {
            if (owner.kind == NodeKind.Package) {
                return PackageAdapter(module, owner)
            }
            owner = owner.owner
        }

        return null
    }

    override fun containingClass(): ClassDoc? {
        if (node.kind == NodeKind.Type) {
            return null
        }

        var owner = node.owner
        while (owner != null) {
            if (owner.kind in NodeKind.classLike) {
                return ClassDocumentationNodeAdapter(module, owner)
            }
            owner = owner.owner
        }

        return null
    }

    override fun isPrivate(): Boolean = false
    override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true
}

open class TypeAdapter(override val module: ModuleNodeAdapter, override val node: DocumentationNode) : Type, HasDocumentationNode, HasModule {
    private val javaLanguageService = JavaLanguageService()

    override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedNameFromType() ?: node.qualifiedNameFromType()
    override fun typeName(): String = javaLanguageService.getArrayElementType(node)?.simpleName() ?: node.simpleName()
    override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName()

    override fun dimension(): String = Collections.nCopies(javaLanguageService.getArrayDimension(node), "[]").joinToString("")
    override fun isPrimitive(): Boolean = simpleTypeName() in setOf("int", "long", "short", "byte", "char", "double", "float", "boolean", "void")

    override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else
            elementType?.asClassDoc() ?:
            when (node.kind) {
                in NodeKind.classLike,
                NodeKind.ExternalClass,
                NodeKind.Exception -> module.classNamed(qualifiedTypeName()) ?: ClassDocumentationNodeAdapter(module, node)

                else -> when {
                    node.links.isNotEmpty() -> TypeAdapter(module, node.links.first()).asClassDoc()
                    else -> ClassDocumentationNodeAdapter(module, node) // TODO ?
                }
            }

    override fun asTypeVariable(): TypeVariable? = if (node.kind == NodeKind.TypeParameter) TypeVariableAdapter(module, node) else null
    override fun asParameterizedType(): ParameterizedType? =
            if (node.details(NodeKind.Type).isNotEmpty() && javaLanguageService.getArrayElementType(node) == null)
                ParameterizedTypeAdapter(module, node)
            else
                null

    override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == NodeKind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null
    override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null
    override fun getElementType(): Type? = javaLanguageService.getArrayElementType(node)?.let { et -> TypeAdapter(module, et) }
    override fun asWildcardType(): WildcardType? = null

    override fun toString(): String = qualifiedTypeName() + dimension()
    override fun hashCode(): Int = node.name.hashCode()
    override fun equals(other: Any?): Boolean = other is TypeAdapter && toString() == other.toString()
}

class NotAnnotatedTypeAdapter(typeAdapter: AnnotatedTypeAdapter) : Type by typeAdapter {
    override fun asAnnotatedType() = null
}

class AnnotatedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), AnnotatedType {
    override fun underlyingType(): Type? = NotAnnotatedTypeAdapter(this)
    override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
}

class WildcardTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), WildcardType {
    override fun extendsBounds(): Array<out Type> = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray()
    override fun superBounds(): Array<out Type> = node.details(NodeKind.LowerBound).map { TypeAdapter(module, it) }.toTypedArray()
}

class TypeVariableAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), TypeVariable {
    override fun owner(): ProgramElementDoc = node.owner!!.let<DocumentationNode, ProgramElementDoc> { owner ->
        when (owner.kind) {
            NodeKind.Function,
            NodeKind.Constructor -> ExecutableMemberAdapter(module, owner)

            NodeKind.Class,
            NodeKind.Interface,
            NodeKind.Enum -> ClassDocumentationNodeAdapter(module, owner)

            else -> ProgramElementAdapter(module, node.owner!!)
        }
    }

    override fun bounds(): Array<out Type>? = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray()
    override fun annotations(): Array<out AnnotationDesc>? = node.members(NodeKind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray()

    override fun qualifiedTypeName(): String = node.name
    override fun simpleTypeName(): String = node.name
    override fun typeName(): String = node.name

    override fun hashCode(): Int = node.name.hashCode()
    override fun equals(other: Any?): Boolean = other is Type && other.typeName() == typeName() && other.asTypeVariable()?.owner() == owner()

    override fun asTypeVariable(): TypeVariableAdapter = this
}

class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType {
    override fun typeArguments(): Array<out Type> = node.details(NodeKind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray()
    override fun superclassType(): Type? =
            node.lookupSuperClasses(module)
                    .firstOrNull { it.kind == NodeKind.Class || it.kind == NodeKind.ExternalClass }
                    ?.let { ClassDocumentationNodeAdapter(module, it) }

    override fun interfaceTypes(): Array<out Type> =
            node.lookupSuperClasses(module)
                    .filter { it.kind == NodeKind.Interface }
                    .map { ClassDocumentationNodeAdapter(module, it) }
                    .toTypedArray()

    override fun containingType(): Type? = when (node.owner?.kind) {
        NodeKind.Package -> null
        NodeKind.Class,
        NodeKind.Interface,
        NodeKind.Object,
        NodeKind.Enum -> ClassDocumentationNodeAdapter(module, node.owner!!)

        else -> null
    }
}

class ParameterAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter {
    override fun typeName(): String? = JavaLanguageService().renderType(node.detail(NodeKind.Type))
    override fun type(): Type? = TypeAdapter(module, node.detail(NodeKind.Type))
    override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
}

class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode, val parent: ExecutableMemberAdapter) : DocumentationNodeAdapter(module, receiverType), Parameter {
    override fun typeName(): String? = receiverType.name
    override fun type(): Type? = TypeAdapter(module, receiverType)
    override fun annotations(): Array<out AnnotationDesc> = nodeAnnotations(this).toTypedArray()
    override fun name(): String = tryName("receiver")

    private tailrec fun tryName(name: String): String = when (name) {
        in parent.parameters().drop(1).map { it.name() } -> tryName("$$name")
        else -> name
    }
}

fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node ->
    val pkg = fqName.substringBeforeLast(".", "")
    if (pkg.isNotEmpty()) {
        node.append(DocumentationNode(pkg, Content.Empty, NodeKind.Package), RefKind.Owner)
    }

    node
}

private fun DocumentationNode.hasNonEmptyContent() =
        this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()


open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), ExecutableMemberDoc {

    override fun isSynthetic(): Boolean = false
    override fun isNative(): Boolean = node.annotations.any { it.name == "native" }

    override fun thrownExceptions(): Array<out ClassDoc> = emptyArray() // TODO
    override fun throwsTags(): Array<out ThrowsTag> =
            node.content.sections
                    .filter { it.tag == ContentTags.Exceptions && it.subjectName != null }
                    .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) }
                    .toTypedArray()

    override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).any { false } // TODO

    override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" }

    override fun paramTags(): Array<out ParamTag> =
            collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })

    override fun thrownExceptionTypes(): Array<out Type> = emptyArray()
    override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) }
    override fun flatSignature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")")
    override fun signature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types

    override fun parameters(): Array<out Parameter> =
            ((receiverNode()?.let { receiver -> listOf<Parameter>(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList())
                    + node.details(NodeKind.Parameter).map { ParameterAdapter(module, it) }
                    ).toTypedArray()

    override fun typeParameters(): Array<out TypeVariable> = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()

    override fun typeParamTags(): Array<out ParamTag> =
            collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })

    private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->
        when {
            receivers.isNotEmpty() -> receivers.single().detail(NodeKind.Type)
            else -> null
        }
    }
}

class ConstructorAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), ConstructorDoc {
    override fun name(): String = node.owner?.name ?: throw IllegalStateException("No owner for $node")

    override fun containingClass(): ClassDoc? {
        return super.containingClass()
    }
}

class MethodAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), MethodDoc {
    override fun overrides(meth: MethodDoc?): Boolean = false // TODO

    override fun overriddenType(): Type? = node.overrides.firstOrNull()?.owner?.let { owner -> TypeAdapter(module, owner) }

    override fun overriddenMethod(): MethodDoc? = node.overrides.map { MethodAdapter(module, it) }.firstOrNull()
    override fun overriddenClass(): ClassDoc? = overriddenMethod()?.containingClass()

    override fun isAbstract(): Boolean = false // TODO

    override fun isDefault(): Boolean = false

    override fun returnType(): Type = TypeAdapter(module, node.detail(NodeKind.Type))

    override fun tags(tagname: String?) = super.tags(tagname)

    override fun tags(): Array<out Tag> {
        val tags = super.tags().toMutableList()
        node.content.findSectionByTag(ContentTags.Return)?.let {
            tags += ReturnTagAdapter(module, this, it.children)
        }

        return tags.toTypedArray()
    }
}

class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), FieldDoc {
    override fun isSynthetic(): Boolean = false

    override fun constantValueExpression(): String? = node.detailOrNull(NodeKind.Value)?.let { it.name }
    override fun constantValue(): Any? = constantValueExpression()

    override fun type(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
    override fun isTransient(): Boolean = node.hasAnnotation(Transient::class)
    override fun serialFieldTags(): Array<out SerialFieldTag> = emptyArray()

    override fun isVolatile(): Boolean = node.hasAnnotation(Volatile::class)
}
open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode)
    : ProgramElementAdapter(module, classNode),
      Type by TypeAdapter(module, classNode),
        ClassDoc {

    override fun name(): String {
        val parent = classNode.owner
        if (parent?.kind in NodeKind.classLike) {
            return parent!!.name + "." + classNode.name
        }
        return classNode.simpleName()
    }

    override fun constructors(filter: Boolean): Array<out ConstructorDoc> = classNode.members(NodeKind.Constructor).map { ConstructorAdapter(module, it) }.toTypedArray()
    override fun constructors(): Array<out ConstructorDoc> = constructors(true)
    override fun importedPackages(): Array<out PackageDoc> = emptyArray()
    override fun importedClasses(): Array<out ClassDoc>? = emptyArray()
    override fun typeParameters(): Array<out TypeVariable> = classNode.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
    override fun asTypeVariable(): TypeVariable? = if (classNode.kind == NodeKind.Class) TypeVariableAdapter(module, classNode) else null
    override fun isExternalizable(): Boolean = interfaces().any { it.qualifiedName() == "java.io.Externalizable" }
    override fun definesSerializableFields(): Boolean = false
    override fun methods(filter: Boolean): Array<out MethodDoc> = classNode.members(NodeKind.Function).map { MethodAdapter(module, it) }.toTypedArray() // TODO include get/set methods
    override fun methods(): Array<out MethodDoc> = methods(true)
    override fun enumConstants(): Array<out FieldDoc>? = classNode.members(NodeKind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray()
    override fun isAbstract(): Boolean = classNode.details(NodeKind.Modifier).any { it.name == "abstract" }
    override fun interfaceTypes(): Array<out Type> = classNode.lookupSuperClasses(module)
            .filter { it.kind == NodeKind.Interface }
            .map { ClassDocumentationNodeAdapter(module, it) }
            .toTypedArray()

    override fun interfaces(): Array<out ClassDoc> = classNode.lookupSuperClasses(module)
            .filter { it.kind == NodeKind.Interface }
            .map { ClassDocumentationNodeAdapter(module, it) }
            .toTypedArray()

    override fun typeParamTags(): Array<out ParamTag> =
            collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })

    override fun fields(): Array<out FieldDoc> = fields(true)
    override fun fields(filter: Boolean): Array<out FieldDoc> = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray()

    override fun findClass(className: String?): ClassDoc? = null // TODO !!!
    override fun serializableFields(): Array<out FieldDoc> = emptyArray()
    override fun superclassType(): Type? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) }
    override fun serializationMethods(): Array<out MethodDoc> = emptyArray() // TODO
    override fun superclass(): ClassDoc? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) }
    override fun isSerializable(): Boolean = false // TODO
    override fun subclassOf(cd: ClassDoc?): Boolean {
        if (cd == null) {
            return false
        }

        val expectedFQName = cd.qualifiedName()
        val types = arrayListOf(classNode)
        val visitedTypes = HashSet<String>()

        while (types.isNotEmpty()) {
            val type = types.removeAt(types.lastIndex)
            val fqName = type.qualifiedName()

            if (expectedFQName == fqName) {
                return true
            }

            visitedTypes.add(fqName)
            types.addAll(type.details(NodeKind.Supertype).filter { it.qualifiedName() !in visitedTypes })
        }

        return false
    }

    override fun innerClasses(): Array<out ClassDoc> = classNode.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
    override fun innerClasses(filter: Boolean): Array<out ClassDoc> = innerClasses()
}

fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) =
        details(NodeKind.Supertype)
                .map { it.links.firstOrNull() }
                .map { module.allTypes[it?.qualifiedName()] }
                .filterNotNull()

fun List<DocumentationNode>.collectAllTypesRecursively(): Map<String, DocumentationNode> {
    val result = hashMapOf<String, DocumentationNode>()

    fun DocumentationNode.collectTypesRecursively() {
        val classLikeMembers = NodeKind.classLike.flatMap { members(it) }
        classLikeMembers.forEach {
            result.put(it.qualifiedName(), it)
            it.collectTypesRecursively()
        }
    }

    forEach { it.collectTypesRecursively() }
    return result
}

class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc {
    val allPackages = module.members(NodeKind.Package).associateBy { it.name }
    val allTypes = module.members(NodeKind.Package).collectAllTypesRecursively()

    override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) }

    override fun classes(): Array<out ClassDoc> =
            allTypes.values.map { ClassDocumentationNodeAdapter(this, it) }.toTypedArray()

    override fun options(): Array<out Array<String>> = arrayOf(
            arrayOf("-d", outputPath),
            arrayOf("-docencoding", "UTF-8"),
            arrayOf("-charset", "UTF-8"),
            arrayOf("-keywords")
    )

    override fun specifiedPackages(): Array<out PackageDoc>? = module.members(NodeKind.Package).map { PackageAdapter(this, it) }.toTypedArray()

    override fun classNamed(qualifiedName: String?): ClassDoc? =
            allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) }

    override fun specifiedClasses(): Array<out ClassDoc> = classes()
}

private fun DocumentationNodeAdapter.collectParamTags(kind: NodeKind, sectionFilter: (ContentSection) -> Boolean) =
        (node.details(kind)
                .filter(DocumentationNode::hasNonEmptyContent)
                .map { ParamTagAdapter(module, this, it.name, true, it.content.children) }

                + node.content.sections
                .filter(sectionFilter)
                .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) })

                .toTypedArray()