package gaf3.core.services.log.config


import com.fasterxml.jackson.annotation.JsonInclude
import gaf3.core.web.condition.ParamExpression
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.util.MultiValueMap

@ConfigurationProperties(prefix = "gaf.log")
public class GafLogConfigure {

    /**
     * 菜单树资源文件
     */
    var routes: List<LogRoute>? = null

    public fun extract(path: String, method: String, queryParams: MultiValueMap<String, String>? = null): LogRoute? {
        return routes?.filter { it.method == method.toLowerCase() || it.method == null }?.filter { it.path != null }?.find { r ->
            var matched = r.path == path || (match(r.path!!, path) != null)
            matched && (queryParams?.let {
                r.expression?.match(it)
            } ?: true)
        }?.let {
            match(it.path!!, path)?.let { m ->
                with(LogRoute()) {
                    logType = it.logType
                    module = it.module
                    event = it.event
                    action = it.action
                    target = m.values.first()
                    this
                }
            } ?: it
        }
    }

    fun match(path1: String, path2: String): Map<String, String>? {
        var pattern = "\\{([^/]+)}"
        val regex0 = Regex(pattern)
        val regex1 = Regex(".*${pattern}.*")
        return regex1.matchEntire(path1)?.let {
            val name = it.groupValues[1]
            val pattern2 = regex0.replace(path1, "([^/]+)")
            val regex2 = Regex(pattern2)
            regex2.matchEntire(path2)?.let { it2 ->
                val value = it2.groupValues[1]
                mapOf(name to value)
            }
        }
    }


    @JsonInclude(JsonInclude.Include.NON_NULL)
    class LogRoute {
        var path: String? = null
        var method: String? = null
        var logType: String? = null
        var module: String? = null
        var event: String? = null
        var action: String? = null
        var target: String? = null
        var params: String? = null
            set(value) {
                expression = ParamExpression(value)
                field = value
            }
        var expression: ParamExpression? = null
    }
}