package godot.annotation.processor.processing

import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated
import godot.annotation.processor.Settings
import godot.annotation.processor.ext.provideRegistrationFilePathForInitialGenerationWithoutExtension
import godot.annotation.processor.visitor.MetadataAnnotationVisitor
import godot.entrygenerator.EntryGenerator
import godot.tools.common.constants.FileExtensions
import godot.tools.common.constants.godotEntryBasePackage

/**
 * Second round:
 *
 * Generates the registration files for the registrars generated by the previous round
 */
internal class RoundGenerateRegistrationFilesForCurrentCompilation(
    override val blackboard: ProcessingRoundsBlackboard,
    override val resolver: Resolver,
    override val codeGenerator: CodeGenerator,
    override val logger: KSPLogger,
    private val settings: Settings,
): BaseRound() {
    override fun executeInternal(): List<KSAnnotated> {
        if (settings.isRegistrationFileGenerationEnabled) {
            val metadataAnnotationVisitor = MetadataAnnotationVisitor()
            resolver.getDeclarationsFromPackage(godotEntryBasePackage).forEach { declaration ->
                declaration.accept(metadataAnnotationVisitor, Unit)
            }

            val metadataToGenerateRegistrationFilesFor = metadataAnnotationVisitor
                .registeredClassMetadataContainers
                .filter { !blackboard.alreadyGeneratedRegistrationFiles.contains(it.fqName) }

            EntryGenerator.generateRegistrationFiles(
                registeredClassMetadataContainers = metadataToGenerateRegistrationFilesFor,
                registrationFileAppendableProvider = { metadata ->
                    blackboard.alreadyGeneratedRegistrationFiles.add(metadata.fqName)

                    val resourcePathFromProjectRoot = provideRegistrationFilePathForInitialGenerationWithoutExtension(
                        isRegistrationFileHierarchyEnabled = settings.isRegistrationFileHierarchyEnabled,
                        fqName = metadata.fqName,
                        registeredName = metadata.registeredName,
                        compilationProjectName = settings.projectName,
                        classProjectName = metadata.projectName,
                        registrationFileOutDir = settings.registrationBaseDirPathRelativeToProjectDir
                    )

                    codeGenerator.createNewFileByPath(
                        Dependencies.ALL_FILES,
                        "entryFiles/${resourcePathFromProjectRoot.removeSuffix(".${FileExtensions.GodotKotlinJvm.registrationFile}")}", // suffix will be added by the codeGenerator of KSP and is defined one line below
                        FileExtensions.GodotKotlinJvm.registrationFile
                    ).bufferedWriter()
                }
            )
        }

        return emptyList()
    }
}
