package de.kif.backend.route


import de.kif.backend.authenticateOrRedirect
import de.kif.backend.repository.TrackRepository
import de.kif.backend.view.MainTemplate
import de.kif.backend.view.MenuTemplate
import de.kif.backend.view.TableTemplate
import de.kif.backend.view.respondMain
import de.kif.common.Search
import de.kif.common.model.Color
import de.kif.common.model.Permission
import de.kif.common.model.Track
import io.ktor.application.call
import io.ktor.html.insert
import io.ktor.html.respondHtmlTemplate
import io.ktor.request.receiveParameters
import io.ktor.response.respondRedirect
import io.ktor.routing.Route
import io.ktor.routing.get
import io.ktor.routing.post
import io.ktor.util.toMap
import kotlinx.css.CSSBuilder
import kotlinx.css.Display
import kotlinx.html.*
import kotlin.collections.set
import kotlin.random.Random

fun DIV.colorPicker(color: Color?) {
    val colorString = color?.toString() ?: Color(
        Random.nextInt(256),
        Random.nextInt(256),
        Random.nextInt(256)
    ).toString()

    var found = false
    fun DIV.generate(colorId: String, c: Color) {
        val name = colorId.replace("-", " ").capitalize()
        div("color-picker-entry") {
            radioInput(name = "color") {
                id = "color-$colorId"
                value = colorId

                if (color == c) {
                    checked = true
                    found = true
                }
            }
            label {
                title = name
                htmlFor = "color-$colorId"
                attributes["style"] = CSSBuilder().apply {
                    backgroundColor = kotlinx.css.Color(c.toString())
                }.toString()
            }
        }
    }
    div("color-picker") {
        for ((name, c) in Color.default) {
            generate(name, c)
        }

        div("color-picker-custom") {
            radioInput(name = "color") {
                id = "color-custom"
                value = "custom"

                if (!found) {
                    checked = true
                }
            }
            label {
                title = "Custom"
                htmlFor = "color-custom"

                input(
                    name = "color-input",
                    type = InputType.color
                ) {
                    value = colorString
                }
            }
        }
    }
}

fun Route.track() {
    get("/tracks") {
        authenticateOrRedirect(Permission.WORK_GROUP) { user ->
            val search = call.parameters["search"] ?: ""
            val list = TrackRepository.all()
            respondMain {
                menuTemplate {
                    this.user = user
                    active = MenuTemplate.Tab.WORK_GROUP
                }
                content {
                    insert(TableTemplate()) {
                        searchValue = search

                        action {
                            a("/track/new") {
                                button(classes = "form-btn btn-primary") {
                                    +"Add track"
                                }
                            }
                        }

                        header {
                            th {
                                +"Name"
                            }
                            th {
                                +"Color"
                            }
                            th(classes = "action") {
                                +"Action"
                            }
                        }

                        for (u in list) {
                            val s = u.createSearch()
                            entry {
                                attributes["style"] = CSSBuilder().apply {
                                    display = if (Search.match(search, s)) Display.tableRow else Display.none
                                }.toString()
                                attributes["data-search"] = s.stringify()
                                td {
                                    +u.name
                                }
                                td {
                                    +u.color.toString()
                                }
                                td(classes = "action") {
                                    a("/track/${u.id}") {
                                        i("material-icons") { +"edit" }
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }
    }

    get("/track/{id}") {
        authenticateOrRedirect(Permission.WORK_GROUP) { user ->
            val trackId = call.parameters["id"]?.toLongOrNull() ?: return@get
            val editTrack = TrackRepository.get(trackId) ?: return@get
            respondMain {
                menuTemplate {
                    this.user = user
                    active = MenuTemplate.Tab.WORK_GROUP
                }
                content {
                    h1 { +"Edit track" }
                    form(method = FormMethod.post) {
                        div("form-group") {
                            label {
                                htmlFor = "name"
                                +"Name"
                            }
                            input(
                                name = "name",
                                classes = "form-control"
                            ) {
                                id = "name"
                                placeholder = "Name"
                                value = editTrack.name
                            }
                        }
                        div("form-group") {
                            colorPicker(editTrack.color)
                        }

                        div("form-group") {
                            a("/track") {
                                button(classes = "form-btn") {
                                    +"Cancel"
                                }
                            }
                            button(type = ButtonType.submit, classes = "form-btn btn-primary") {
                                +"Save"
                            }
                        }
                    }
                    a("/track/${editTrack.id}/delete") {
                        button(classes = "form-btn btn-danger") {
                            +"Delete"
                        }
                    }
                }
            }
        }
    }

    post("/track/{id}") {
        authenticateOrRedirect(Permission.WORK_GROUP) { user ->
            val trackId = call.parameters["id"]?.toLongOrNull() ?: return@post
            val params = call.receiveParameters().toMap().mapValues { (_, list) ->
                list.firstOrNull()
            }
            var editTrack = TrackRepository.get(trackId) ?: return@post

            params["name"]?.let { editTrack = editTrack.copy(name = it) }

            editTrack = editTrack.copy(color = (params["color"] ?: return@post).let { c ->
                Color.default.find { it.first == c }
            }?.second ?: (params["color-input"] ?: return@post).let(Color.Companion::parse))

            TrackRepository.update(editTrack)

            call.respondRedirect("/tracks")
        }
    }

    get("/track/new") {
        authenticateOrRedirect(Permission.WORK_GROUP) { user ->
            respondMain {
                menuTemplate {
                    this.user = user
                    active = MenuTemplate.Tab.WORK_GROUP
                }
                content {
                    h1 { +"Create track" }
                    form(method = FormMethod.post) {
                        div("form-group") {
                            label {
                                htmlFor = "name"
                                +"Name"
                            }
                            input(
                                name = "name",
                                classes = "form-control"
                            ) {
                                id = "name"
                                placeholder = "Name"
                                value = ""
                            }
                        }
                        div("form-group") {
                            colorPicker(null)
                        }
                        div("form-group") {
                            a("/track") {
                                button(classes = "form-btn") {
                                    +"Cancel"
                                }
                            }
                            button(type = ButtonType.submit, classes = "form-btn btn-primary") {
                                +"Create"
                            }
                        }
                    }
                }
            }
        }
    }

    post("/track/new") {
        authenticateOrRedirect(Permission.WORK_GROUP) { user ->
            val params = call.receiveParameters().toMap().mapValues { (_, list) ->
                list.firstOrNull()
            }

            val name = params["name"] ?: return@post
            val color = (params["color"] ?: return@post).let { c ->
                Color.default.find { it.first == c }
            }?.second ?: (params["color-input"] ?: return@post).let(Color.Companion::parse)

            val track = Track(null, name, color)

            TrackRepository.create(track)

            call.respondRedirect("/tracks")
        }
    }

    get("track/{id}/delete") {
        authenticateOrRedirect(Permission.WORK_GROUP) { user ->
            val trackId = call.parameters["id"]?.toLongOrNull() ?: return@get

            TrackRepository.delete(trackId)

            call.respondRedirect("/tracks")
        }
    }
}
