/*
 * ImageToolbox is an image editor for android
 * Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * 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.
 *
 * You should have received a copy of the Apache License
 * along with this program.  If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
 */

@file:Suppress("unused")

package com.t8rin.imagetoolbox.core.ksp.processor

import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration

internal class FilterInjectProcessor : SymbolProcessorProvider {
    override fun create(
        environment: SymbolProcessorEnvironment
    ): SymbolProcessor = FilterInjectProcessorImpl(environment)
}

private class FilterInjectProcessorImpl(
    environment: SymbolProcessorEnvironment
) : SymbolProcessor {

    private val logger = environment.logger
    private val codegen = environment.codeGenerator

    override fun process(resolver: Resolver): List<KSAnnotated> {
        logger.warn("START generation of filter map")
        val annotationFqn = "$PACKAGE.core.ksp.annotations.FilterInject"

        val annotated = resolver.getSymbolsWithAnnotation(annotationFqn)
            .filterIsInstance<KSClassDeclaration>()
            .sortedBy { it.simpleName.asString() }
            .toList()

        if (annotated.isEmpty()) {
            logger.warn("No annotated classes found")
            return emptyList()
        }

        val fileName = "FilterMappings"
        val packageName = "$PACKAGE.generated"
        val files = annotated.mapNotNull { it.containingFile }.toTypedArray()

        val file = codegen.createNewFile(
            dependencies = Dependencies(false, *files),
            packageName = packageName,
            fileName = fileName
        )

        file.bufferedWriter().use { writer ->
            writer.apply {
                appendLine("// Generated by KSP — do not edit")
                appendLine("package $PACKAGE.generated")
                appendLine()
                appendLine("import android.graphics.Bitmap")
                appendLine("import $PACKAGE.core.domain.transformation.*")
                appendLine("import $PACKAGE.feature.filters.data.model.*")
                appendLine("import $PACKAGE.core.filters.domain.model.*")
                appendLine()
                appendLine("internal fun mapFilter(filter: Filter<*>): Transformation<Bitmap> = filter.run {")
                appendLine("    when (this) {")

                annotated.forEach { filter ->
                    val filterName = filter.simpleName.asString()
                    appendLine("        is Filter.${filterName.removeSuffix("Filter")} -> ${filterName}(value)")
                }

                appendLine()
                appendLine("        else -> throw IllegalArgumentException(\"No filter implementation for interface \${this::class.simpleName}\")")
                appendLine("    }")
                appendLine("}")
            }
        }

        logger.info("FilterMappings generated successfully")

        return emptyList()
    }

    companion object {
        private const val PACKAGE = "com.t8rin.imagetoolbox"
    }
}