/*
 * 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.FunctionSummaryList
import com.google.devsite.PropertySummaryList
import com.google.devsite.TypeSummaryItem
import com.google.devsite.WithDescriptionList
import com.google.devsite.components.DescriptionComponent
import com.google.devsite.components.Link
import com.google.devsite.components.impl.DefaultDevsitePage
import com.google.devsite.components.impl.DefaultDevsitePlatformSelector
import com.google.devsite.components.impl.DefaultPackageSummary
import com.google.devsite.components.impl.DefaultSummaryList
import com.google.devsite.components.impl.DefaultUnlink
import com.google.devsite.components.pages.DevsitePage
import com.google.devsite.components.pages.PackageSummary
import com.google.devsite.components.symbols.FunctionSignature
import com.google.devsite.components.symbols.PropertySignature
import com.google.devsite.components.symbols.SymbolDetail
import com.google.devsite.components.table.SummaryList
import com.google.devsite.components.table.TableRowSummaryItem
import com.google.devsite.renderer.Language
import com.google.devsite.renderer.impl.DocumentablesHolder
import com.google.devsite.renderer.impl.paths.FilePathProvider
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import org.jetbrains.dokka.model.DFunction
import org.jetbrains.dokka.model.DPackage
import org.jetbrains.dokka.model.DProperty
import org.jetbrains.dokka.model.Documentable

/** Converts documentables into components for the package summary page. */
internal abstract class PackageDocumentableConverter(
    private val displayLanguage: Language,
    private val dPackage: DPackage,
    private val pathProvider: FilePathProvider,
    private val docsHolder: DocumentablesHolder,
    protected val functionConverter: FunctionDocumentableConverter,
    protected val propertyConverter: PropertyDocumentableConverter,
    protected val javadocConverter: DocTagConverter,
    protected val paramConverter: ParameterDocumentableConverter
) {
    protected abstract val header: DefaultDevsitePlatformSelector?
    protected abstract val functionToSummaryConverter:
        (DFunction, ModifierHints) -> TypeSummaryItem<FunctionSignature>?
    protected abstract val functionToDetailConverter:
        (DFunction, ModifierHints) -> SymbolDetail<FunctionSignature>?
    protected abstract val propertyToSummaryConverter:
        (DProperty, ModifierHints) -> TypeSummaryItem<PropertySignature>?
    protected abstract val propertyToDetailConverter:
        (DProperty, ModifierHints) -> SymbolDetail<PropertySignature>?
    protected abstract val docsToSummary:
        (List<Documentable>) -> SummaryList<TableRowSummaryItem<Link, DescriptionComponent>>

    /** @return the root component for the package summary page */
    suspend fun summaryPage(): DevsitePage<PackageSummary> = coroutineScope {
        val interfaces = async {
            docsToSummary(docsHolder.interfacesFor(dPackage))
        }
        val classes = async {
            docsToSummary(docsHolder.classesFor(dPackage, displayLanguage))
        }
        val enums = async { docsToSummary(docsHolder.enumsFor(dPackage)) }
        val objects = async {
            docsToSummary(
                docsHolder.interestingObjectsFor(dPackage, displayLanguage)
            )
        }
        val exceptions = async {
            docsToSummary(docsHolder.exceptionsFor(dPackage))
        }
        val annotations = async {
            docsToSummary(docsHolder.annotationsFor(dPackage))
        }
        @Suppress("UNCHECKED_CAST") val typeAliases = async {
            docsToSummary(docsHolder.typeAliasesFor(dPackage)) as WithDescriptionList<DefaultUnlink>
        }

        val topLevelConstantsSummary = async { propertiesToSummary(topLevelConstants()) }
        val topLevelPropertiesSummary = async { propertiesToSummary(topLevelProperties()) }
        val topLevelFunctionsSummary = async { functionsToSummary(topLevelFunctions()) }
        val extensionPropertiesSummary = async { propertiesToSummary(extensionProperties()) }
        val extensionFunctionsSummary = async { functionsToSummary(extensionFunctions()) }

        val topLevelConstants = async { propertiesToDetail(topLevelConstants()) }
        val topLevelProperties = async { propertiesToDetail(topLevelProperties()) }
        val topLevelFunctions = async { functionsToDetail(topLevelFunctions()) }
        val extensionProperties = async { propertiesToDetail(extensionProperties()) }
        val extensionFunctions = async { functionsToDetail(extensionFunctions()) }

        DefaultDevsitePage(
            DevsitePage.Params(
                displayLanguage,
                path = pathProvider.forReference(dPackage.dri).url,
                bookPath = pathProvider.book,
                title = dPackage.name,
                content = DefaultPackageSummary(
                    PackageSummary.Params(
                        header,
                        displayLanguage,
                        description = javadocConverter.metadata(
                            documentable = dPackage,
                            isFromJava = false // This parameter is not used in the DPackage case
                        ),
                        interfaces = interfaces.await(),
                        classes = classes.await(),
                        enums = enums.await(),
                        objects = objects.await(),
                        exceptions = exceptions.await(),
                        annotations = annotations.await(),
                        typeAliases = typeAliases.await(),
                        topLevelConstantsSummary = topLevelConstantsSummary.await(),
                        topLevelPropertiesSummary = topLevelPropertiesSummary.await(),
                        topLevelFunctionsSummary = topLevelFunctionsSummary.await(),
                        extensionPropertiesSummary = extensionPropertiesSummary.await(),
                        extensionFunctionsSummary = extensionFunctionsSummary.await(),
                        topLevelConstants = topLevelConstants.await(),
                        topLevelProperties = topLevelProperties.await(),
                        topLevelFunctions = topLevelFunctions.await(),
                        extensionProperties = extensionProperties.await(),
                        extensionFunctions = extensionFunctions.await()
                    )
                ),
                metadataComponent = null,
                includedHeadTagPath = pathProvider.includedHeadTagsPath,
            )
        )
    }

    private fun functionsToSummary(functions: List<DFunction>): FunctionSummaryList {
        val components = functions.mapNotNull {
            val modifierHints = ModifierHints(
                displayLanguage = displayLanguage,
                type = DFunction::class.java,
                containingType = DPackage::class.java,
                isFromJava = it.isFromJava(),
                isSummary = true
            )
            functionToSummaryConverter(it, modifierHints)
        }

        return DefaultSummaryList(
            SummaryList.Params(
                items = components
            )
        )
    }

    private fun functionsToDetail(functions: List<DFunction>):
        List<SymbolDetail<FunctionSignature>> {
        return functions.mapNotNull {
            val modifierHints = ModifierHints(
                displayLanguage = displayLanguage,
                type = DFunction::class.java,
                containingType = DPackage::class.java,
                isFromJava = it.isFromJava(),
                isSummary = false
            )
            functionToDetailConverter(it, modifierHints)
        }
    }

    private fun propertiesToSummary(properties: List<DProperty>): PropertySummaryList {
        val components = properties.mapNotNull {
            val modifierHints = ModifierHints(
                displayLanguage = displayLanguage,
                type = DProperty::class.java,
                containingType = DPackage::class.java,
                isFromJava = it.isFromJava(),
                isSummary = true
            )
            propertyToSummaryConverter(it, modifierHints)
        }

        return DefaultSummaryList(
            SummaryList.Params(
                items = components
            )
        )
    }

    private fun propertiesToDetail(properties: List<DProperty>):
        List<SymbolDetail<PropertySignature>> {
        return properties.mapNotNull {
            val modifierHints = ModifierHints(
                displayLanguage = displayLanguage,
                type = DProperty::class.java,
                containingType = DPackage::class.java,
                isFromJava = it.isFromJava(),
                isSummary = false
            )
            propertyToDetailConverter(it, modifierHints)
        }
    }

    private fun topLevelConstants() = dPackage.properties
        .filter { it.isConstant() }
        .sortedBy { it.name }

    private fun topLevelProperties() = dPackage.properties
        .filterNot { it.isConstant() }
        .filter { it.receiver == null }
        .sortedBy { it.name }

    private fun topLevelFunctions() = dPackage.functions
        .filter { it.receiver == null }
        .sortedBy { it.name + " " + it.dri }

    private fun extensionProperties() = dPackage.properties
        .filterNot { it.receiver == null }
        .sortedBy { it.name }

    private fun extensionFunctions() = dPackage.functions
        .filterNot { it.receiver == null }
        .sortedBy { it.name + " " + it.dri }
}
