package de.kif.backend.view

import de.kif.backend.PortalSession
import de.kif.backend.Resources
import de.kif.backend.prefix
import de.kif.common.model.User
import io.ktor.application.ApplicationCall
import io.ktor.application.call
import io.ktor.html.Placeholder
import io.ktor.html.Template
import io.ktor.html.insert
import io.ktor.html.respondHtmlTemplate
import io.ktor.request.path
import io.ktor.request.uri
import io.ktor.response.respondRedirect
import io.ktor.sessions.get
import io.ktor.sessions.sessions
import io.ktor.util.pipeline.PipelineContext
import kotlinx.html.*

class MainTemplate(
    private val theme: Theme,
    private val url: String,
    private val user: User?,
    private val noMenu: Boolean,
    private val stretch: Boolean
) : Template<HTML> {
    val content = Placeholder<HtmlBlockTag>()

    override fun HTML.apply() {
        head {
            meta(charset = "utf-8")
            meta(name = "viewport", content = "width=device-width, initial-scale=1.0")

            title("KIF Portal")

            link(href = "$prefix/static/external/material-icons.css", type = LinkType.textCss, rel = LinkRel.stylesheet)
            link(
                href = "$prefix/static/external/font/Montserrat.css",
                type = LinkType.textCss,
                rel = LinkRel.stylesheet
            )
            link(
                href = "https://fonts.googleapis.com/css?family=Bungee|Oswald|Raleway",
                type = LinkType.textCss,
                rel = LinkRel.stylesheet
            )
            link(href = "$prefix/static/style/style.css", type = LinkType.textCss, rel = LinkRel.stylesheet)

            when (theme) {
                Theme.LIGHT -> {
                    // Ignore
                }
                Theme.DARK -> {
                    link(href = "$prefix/static/style/dark.css", type = LinkType.textCss, rel = LinkRel.stylesheet)
                }
                Theme.PRINCESS -> {
                    link(href = "$prefix/static/style/princess.css", type = LinkType.textCss, rel = LinkRel.stylesheet)
                }
                Theme.BRETT -> {
                    link(href = "$prefix/static/style/board.css", type = LinkType.textCss, rel = LinkRel.stylesheet)
                }
            }

            script(src = "$prefix/static/require.min.js") {}

            script {
                unsafe {
                    +"let prefix = '$prefix';\n"
                    +"require.config({baseUrl: '$prefix/static'});\n"
                    +"require([${Resources.jsModules}]);\n"
                }
            }
        }
        body {
            if (!noMenu) {
                insert(MenuTemplate(url, user)) {}
            }

            val containerClasses = if (stretch) "container-full" else "container"
            div(containerClasses) {
                div("main") {
                    insert(content)
                }
            }

            if (!noMenu) {
                div("footer") {
                    div("container") {
                        div("footer-credit") {
                        }
                        div("footer-theme") {
                            for ((it, text) in Theme.displayThemes) {
                                a("?theme=${it.name}", classes = if (theme == it) "selected" else "") {
                                    id = "theme-${it.name.toLowerCase()}"
                                    +text.capitalize()
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

enum class Theme(val text: String, val display: Boolean, val dark: Boolean, val primaryColor: String) {
    LIGHT("Hell", true, false, "#B11D33"),
    DARK("Dunkel", true, true, "#ef5350"),
    PRINCESS("Barbie", true, false, "#B11D33"),
    BRETT("Brett", false, false, "#B11D33");

    companion object {
        private val lookup = values().toList().associateBy { it.name }

        val displayThemes = values().filter { it.display }.map { it to it.text.toLowerCase() }

        fun lookup(name: String?): Theme {
            return lookup[(name ?: return LIGHT).toUpperCase()] ?: LIGHT
        }
    }
}

suspend fun PipelineContext<Unit, ApplicationCall>.respondMain(
    noMenu: Boolean = false,
    stretch: Boolean = false,
    body: MainTemplate.(Theme) -> Unit
) {
    val param = call.request.queryParameters["theme"]
    val url = call.request.uri.substring(1 + prefix.length)
    val user = call.sessions.get<PortalSession>()?.getUser(call)

    if (param != null) {
        call.response.cookies.append(
            name = "theme",
            value = Theme.lookup(param).name,
            maxAge = Int.MAX_VALUE,
            path = "$prefix/"
        )
        call.respondRedirect(call.request.path())
    } else {
        val theme = Theme.lookup(call.request.cookies["theme"])
        call.respondHtmlTemplate(
            MainTemplate(
                theme,
                url,
                user,
                noMenu,
                stretch
            )
        ) {
            body(theme)
        }
    }
}
