package net.taehui.twilight.taehui

import com.fasterxml.jackson.databind.ObjectMapper
import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.codec.http.*
import io.netty.util.CharsetUtil
import net.taehui.twilight.Logger
import net.taehui.twilight.Utility
import net.taehui.twilight.system.AvatarHandler
import net.taehui.twilight.system.Configure
import org.slf4j.LoggerFactory
import java.net.InetSocketAddress
import java.net.URLDecoder
import java.nio.charset.StandardCharsets
import java.nio.file.Files

class TaehuiAvatar : SimpleChannelInboundHandler<FullHttpRequest>(), Logger {
    class QwilightDate {
        var date = ""
        var hash = ""
        var title = ""
        var title64 = ""
    }

    private var avatarIP = ""

    fun send(handler: ChannelHandlerContext) {
        val r = DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NO_CONTENT)
        val hs = r.headers()
        hs[HttpHeaderNames.CONTENT_TYPE] = "application/text"
        hs[HttpHeaderNames.CONTENT_ENCODING] = CharsetUtil.UTF_8
        handler.writeAndFlush(r).addListener(ChannelFutureListener.CLOSE)
    }

    override fun channelActive(ctx: ChannelHandlerContext) {
        avatarIP = (ctx.channel().remoteAddress() as InetSocketAddress).address.hostAddress
    }

    public override fun channelRead0(ctx: ChannelHandlerContext, msg: FullHttpRequest) {
        val path = URLDecoder.decode(msg.uri(), StandardCharsets.UTF_8)
        val mode = msg.method()
        logInfo("$mode $path")
        if (mode == HttpMethod.PATCH) {
            when (path) {
                "/date" -> {
                    val data = msg.content().toString(StandardCharsets.UTF_8).split(" ".toRegex())
                    var date = data[0]
                    val hash = data[1]
                    if (date.contains("!")) {
                        Configure.hash.clear()
                    }
                    date = date.replace("!", "")
                    Configure.hash.add(hash)
                    Configure.saveConfigure()
                    val jm = ObjectMapper()
                    val qwilightDateFilePath = Configure.path.wwwPath.resolve(Configure.path.datePath)
                    val qwilightDate = jm.readValue(Files.readString(qwilightDateFilePath), QwilightDate::class.java)
                    qwilightDate.date = date
                    qwilightDate.hash = hash
                    Files.newBufferedWriter(qwilightDateFilePath)
                        .use { jm.writerWithDefaultPrettyPrinter().writeValue(it, qwilightDate) }
                    send(ctx)
                }

                "/drawing" -> {
                    AvatarHandler.sendInvalidateAvatarDrawing(msg.content().toString(StandardCharsets.UTF_8))
                    send(ctx)
                }

                "/totem" -> {
                    AvatarHandler.handleNotSignIn(msg.content().toString(StandardCharsets.UTF_8))
                    send(ctx)
                }

                else -> ctx.writeAndFlush(DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND))
                    .addListener(
                        ChannelFutureListener.CLOSE
                    )
            }
        } else {
            ctx.writeAndFlush(DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.METHOD_NOT_ALLOWED))
                .addListener(
                    ChannelFutureListener.CLOSE
                )
        }
    }

    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        logFault(cause)
    }

    override fun logInfo(toNotify: String) {
        LoggerFactory.getLogger(javaClass).info("[{}] {}", avatarIP, toNotify)
    }

    override fun logFault(e: Throwable) {
        if (Utility.isValidFault(e)) {
            LoggerFactory.getLogger(javaClass).error("[{}] {}", avatarIP, Utility.getFaultText(e))
        }
    }
}