/*
 * 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.impl

import com.google.devsite.renderer.Language
import com.google.devsite.renderer.converters.explodedChildren
import com.google.devsite.renderer.converters.filterOutJvmSynthetic
import com.google.devsite.renderer.converters.isExceptionClass
import com.google.devsite.renderer.converters.name
import com.google.devsite.renderer.converters.withJavaSynthetic
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import org.jetbrains.dokka.links.DRI
import org.jetbrains.dokka.links.withClass
import org.jetbrains.dokka.model.DAnnotation
import org.jetbrains.dokka.model.DClass
import org.jetbrains.dokka.model.DClasslike
import org.jetbrains.dokka.model.DEnum
import org.jetbrains.dokka.model.DFunction
import org.jetbrains.dokka.model.DInterface
import org.jetbrains.dokka.model.DModule
import org.jetbrains.dokka.model.DPackage
import org.jetbrains.dokka.model.DProperty
import org.jetbrains.dokka.model.DTypeAlias
import org.jetbrains.dokka.model.Documentable
import org.jetbrains.dokka.model.JavaModifier
import org.jetbrains.dokka.model.JavaVisibility
import org.jetbrains.dokka.model.WithSources
import org.jetbrains.dokka.model.properties.PropertyContainer

/**
 * Centralized place to retrieve documentables.
 *
 * All doc rewriting should occur here.
 */
internal class DocumentablesHolder(module: DModule, scope: CoroutineScope) {
    private val packages = scope.async { computePackages(module) }

    private val classlikes = mutableMapOf<DRI, Deferred<List<DClasslike>>>()
    private val classes = mutableMapOf<DRI, Deferred<List<DClass>>>()
    private val syntheticClasses = mutableMapOf<DRI, Deferred<List<DClass>>>()
    private val enums = mutableMapOf<DRI, Deferred<List<DEnum>>>()
    private val interfaces = mutableMapOf<DRI, Deferred<List<DInterface>>>()
    private val annotations = mutableMapOf<DRI, Deferred<List<DAnnotation>>>()
    private val typeAliases = mutableMapOf<DRI, Deferred<List<DTypeAlias>>>()
    private val exceptions = mutableMapOf<DRI, Deferred<List<DClass>>>()

    private val allClasslikes: Deferred<List<DClasslike>>
    private val nestedClasslikesJob: Job
    private val nestedClasslikes = mutableMapOf<DRI, Deferred<List<DClasslike>>>()
    private val subclassGraph: Deferred<Map<DRI, Subclasses>>

    init {
        scope.apply {
            for (packageDoc in module.packages) {
                val children = async { packageDoc.explodedChildren }
                val syntheticClassList = async { computeSyntheticClasses(packageDoc) }
                val classlikesList = async { computeClasslikes(children.await(),
                    syntheticClassList.await()) }
                val classList = async { computeClasses(children.await()) }

                val enumList = async { computeEnums(children.await()) }
                val interfaceList = async { computeInterfaces(children.await()) }
                val annotationList = async { computeAnnotations(children.await()) }
                val typeAliasList = async { computeTypesAliases(packageDoc) }
                val exceptionList = async { computeExceptions(children.await()) }

                classlikes[packageDoc.dri] = classlikesList
                classes[packageDoc.dri] = classList
                syntheticClasses[packageDoc.dri] = syntheticClassList
                enums[packageDoc.dri] = enumList
                interfaces[packageDoc.dri] = interfaceList
                annotations[packageDoc.dri] = annotationList
                typeAliases[packageDoc.dri] = typeAliasList
                exceptions[packageDoc.dri] = exceptionList
            }
        }

        allClasslikes = scope.async { computeClasslikes(module, syntheticClasses) }
        subclassGraph = scope.async { computeSubclassGraph(allClasslikes.await()) }

        nestedClasslikesJob = scope.launch {
            for (classlike in allClasslikes.await()) {
                val nestedClasslikesList =
                    async { computeClasslikes(classlike.explodedChildren) }

                nestedClasslikes[classlike.dri] = nestedClasslikesList
            }
        }
    }

    suspend fun packages(): List<DPackage> = packages.await()

    suspend fun allClasslikes(): List<DClasslike> = allClasslikes.await()

    suspend fun subclassGraph(): Map<DRI, Subclasses> = subclassGraph.await()

    suspend fun classlikesFor(packageDoc: DPackage): List<DClasslike> =
        classlikes.getValue(packageDoc.dri).await()

    suspend fun classlikesFor(classlike: DClasslike): List<DClasslike> {
        nestedClasslikesJob.join()
        return nestedClasslikes.getValue(classlike.dri).await()
    }

    suspend fun classesFor(packageDoc: DPackage, displayLanguage: Language): List<DClass> {
        if (displayLanguage == Language.JAVA) {
            return (classes.getValue(packageDoc.dri).await() +
                syntheticClasses.getValue(packageDoc.dri).await()).sortedBy { it.name() }
            } else {
            return classes.getValue(packageDoc.dri).await()
        }
    }

    suspend fun enumsFor(packageDoc: DPackage): List<DEnum> =
        enums.getValue(packageDoc.dri).await()

    suspend fun interfacesFor(packageDoc: DPackage): List<DInterface> =
        interfaces.getValue(packageDoc.dri).await()

    suspend fun annotationsFor(packageDoc: DPackage): List<DAnnotation> =
        annotations.getValue(packageDoc.dri).await()

    suspend fun typeAliasesFor(packageDoc: DPackage): List<DTypeAlias> =
        typeAliases.getValue(packageDoc.dri).await()

    suspend fun exceptionsFor(packageDoc: DPackage): List<DClass> =
        exceptions.getValue(packageDoc.dri).await()

    private fun computePackages(module: DModule): List<DPackage> {
        return module.packages.sortedBy { it.name }
    }

    private suspend fun computeClasslikes(
        module: DModule,
        syntheticClasses: MutableMap<DRI, Deferred<List<DClass>>>
    ): List<DClasslike> {
        return computeClasslikes(module.packages.flatMap { classlikesFor(it) }) +
            syntheticClasses.values.flatMap { it.await() }
    }

    private fun computeClasslikes(
        docs: List<Documentable>,
        syntheticClasses: List<DClass> = emptyList()
    ): List<DClasslike> {
        return (docs.filterIsInstance<DClasslike>() + syntheticClasses).sortedBy { it.name() }
    }

    private fun computeClasses(docs: List<Documentable>): List<DClass> {
        return docs.filterIsInstance<DClass>().filterNot { it.isExceptionClass }.sortedBy {
            it.name()
        }
    }

    /** Computes the syntheticClasses from top level functions that are used to document Kotlin as
     * Java
     */
    private fun computeSyntheticClasses(packageDoc: DPackage): List<DClass> {
        // functions that are JvmSynthetic are not accessible from Java so they should not appear
        // in the documentation
        val javaFunctions = packageDoc.functions.filterOutJvmSynthetic()
        val javaProperties = packageDoc.properties.filterOutJvmSynthetic()
        return (javaFunctions + javaProperties)
            .mapToSyntheticNames()
            .map { (syntheticClassName, nodes) ->
                DClass(
                    dri = packageDoc.dri.withClass(syntheticClassName),
                    name = syntheticClassName,
                    // TODO (b/168340963) handle kotlin as java properties
                    properties = nodes.filterIsInstance<DProperty>(),
                    constructors = emptyList(),
                    functions = nodes.filterIsInstance<DFunction>().map {
                        it.withJavaSynthetic(syntheticClassName)
                    }.sortedBy { it.name },
                    classlikes = emptyList(),
                    sources = emptyMap(),
                    expectPresentInSet = null,
                    visibility = packageDoc.sourceSets.map { it to JavaVisibility.Public }.toMap(),
                    companion = null,
                    generics = emptyList(),
                    supertypes = emptyMap(),
                    documentation = emptyMap(),
                    modifier = packageDoc.sourceSets.map { it to JavaModifier.Final }.toMap(),
                    sourceSets = packageDoc.sourceSets,
                    isExpectActual = false,
                    extra = PropertyContainer.empty()
                )
            }
    }

    /** Returns a map from String name of synthetic class that this Function (WithSources) would be
     * in to the Functions that are part of those classes
     *
     * This method uses the filename with "Kt" appended
     * TODO(b/173138586): this should be using @file:jvmname when that's fixed by JB
     * **/
    private fun <T : WithSources> List<T>.mapToSyntheticNames() =
        map { it.sources to it }
            .groupBy({ (location, _) ->
                location.let {
                    it.entries.first().value.path.split("/").last().split(".").first() + "Kt"
                }
            }) { it.second }

    private fun computeEnums(docs: List<Documentable>): List<DEnum> {
        return docs.filterIsInstance<DEnum>().sortedBy { it.name() }
    }

    private fun computeInterfaces(docs: List<Documentable>): List<DInterface> {
        return docs.filterIsInstance<DInterface>().sortedBy { it.name() }
    }

    private fun computeAnnotations(docs: List<Documentable>): List<DAnnotation> {
        return docs.filterIsInstance<DAnnotation>().sortedBy { it.name() }
    }

    private fun computeTypesAliases(packageDoc: DPackage): List<DTypeAlias> {
        return packageDoc.typealiases.sortedBy { it.name }
    }

    private fun computeExceptions(docs: List<Documentable>): List<DClass> {
        return docs.filterIsInstance<DClass>().filter { it.isExceptionClass }.sortedBy { it.name() }
    }
}
