package org.pixelndice.table.pixelserver.connection.main.state04joingame

import com.google.common.base.Throwables
import org.apache.logging.log4j.LogManager
import org.hibernate.Session
import org.pixelndice.table.pixelprotocol.Protobuf
import org.pixelndice.table.pixelserver.connection.main.Context
import org.pixelndice.table.pixelserver.connection.main.State
import org.pixelndice.table.pixelserver.connection.main.State03JoinOrHostGame
import org.pixelndice.table.pixelserver.sessionFactory
import org.pixelndice.table.pixelserverhibernate.Game
import org.pixelndice.table.pixelserverhibernate.RPGGameSystem

private val logger = LogManager.getLogger(State05WaitingQueryGame::class.java)

class State05WaitingQueryGame: State {

    override fun process(ctx: Context) {

        // one get operation
        val p = ctx.channel.packet

        val resp = Protobuf.Packet.newBuilder()

        if (p != null) {
            if (p.payloadCase == Protobuf.Packet.PayloadCase.QUERYGAME) {

                var session: Session? = null

                try {
                    session = sessionFactory.openSession()
                    val query = session.createNamedQuery("gameByUUID", Game::class.java)
                    query.setParameter("uuid", p.queryGame.uuid)

                    val list = query.list()

                    if (list.isEmpty()) {

                        val notFound = Protobuf.GameNotFound.newBuilder()
                        resp.gameNotFound = notFound.build()

                        ctx.channel.packet = resp.build()

                    } else {

                        val gameFound = list.get(0)

                        val gameByUUID = Protobuf.GameByUUID.newBuilder()
                        val game = Protobuf.Game.newBuilder()
                        game.uuid = p.queryGame.uuid

                        val gm = Protobuf.Account.newBuilder()

                        gm.id = gameFound.gm!!.id!!
                        gm.email = gameFound.gm!!.email
                        gm.name = gameFound.gm!!.name
                        game.gm = gm.build()

                        game.campaign = gameFound.campaign
                        game.rpgGameSystem = RPGGameSystem.toProtobuf(gameFound.rpgGameSystem)
                        game.hostname = gameFound.hostname
                        game.port = gameFound.port

                        gameByUUID.game = game.build()

                        resp.gameByUuid = gameByUUID.build()

                        ctx.channel.packet = resp.build()
                    }

                    ctx.state = State03JoinOrHostGame()

                }catch (e: Exception){
                    logger.fatal("Hibernate fatal error!")
                    logger.fatal(Throwables.getStackTraceAsString(e))
                }finally {
                    session?.close()
                }

            }else{
                logger.error("Expecting QueryGame. Instead Received: $p")

                val rend = Protobuf.EndWithError.newBuilder()
                rend.reason = "key.expectingquerygame"

                resp.setEndWithError(rend)
                ctx.channel.packet = resp.build()
            }
        }
    }
}