package xyz.r0r5chach.dermy_app.map

import com.badlogic.gdx.ApplicationListener
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.assets.AssetManager
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.PerspectiveCamera
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g3d.Model
import com.badlogic.gdx.graphics.g3d.ModelBatch
import com.badlogic.gdx.graphics.g3d.ModelInstance
import com.badlogic.gdx.math.Vector3
import com.badlogic.gdx.math.collision.BoundingBox
import xyz.r0r5chach.dermy_app.map.locations.Location

class BodyMap(val observer: (Location?) -> Unit, private val backgroundColor: Int): ApplicationListener {
    private val environment: MapEnvironment = MapEnvironment()
    private var bodyModel: Model? = null
    private var modelBatch: ModelBatch? = null
    private var spriteBatch: SpriteBatch? = null
    private var mapInstance: ModelInstance? = null
    private var cam: PerspectiveCamera? = null
    private var camController: MapCameraController? = null
    private var assetManager: AssetManager = AssetManager()
    private var font: BitmapFont? = null



    private fun initModel() {
        bodyModel = assetManager.get(Gdx.files.internal("human.obj").path())
        mapInstance = ModelInstance(bodyModel)
        val modelCenter = Vector3()

        mapInstance!!.calculateBoundingBox(BoundingBox()).getCenter(modelCenter)
        mapInstance!!.transform.translate(-modelCenter.x, -modelCenter.y, -modelCenter.z)
    }

    private fun initCam() {
        cam = PerspectiveCamera(67f, Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat())
        camController = MapCameraController(cam, null)

        cam!!.position[0f, 5f] = 25f
        cam!!.lookAt(0f, 0f, 0f)
        cam!!.near = 1f
        cam!!.far = 300f
        cam!!.update()

        Gdx.input.inputProcessor = camController
    }

    override fun create() {
        assetManager.load(Gdx.files.internal("human.obj").path(), Model::class.java)
        initCam()
        modelBatch = ModelBatch()
        spriteBatch = SpriteBatch()

        font = BitmapFont()
        font!!.color = Color.WHITE
        font!!.data.scale(5f)
    }

    override fun render() {
        camController!!.update()
        assetManager.update()

        Gdx.gl.glClearColor(
            ((backgroundColor shr 0) and 0xFF) / 255f,
            ((backgroundColor shr 8) and 0xFF) / 255f,
            ((backgroundColor shr 16) and 0xFF) / 255f,
            ((backgroundColor shr 24) and 0xFF) / 255f)

        Gdx.gl.glViewport(0, 0, Gdx.graphics.width, Gdx.graphics.height)
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT or GL20.GL_DEPTH_BUFFER_BIT)

        if (assetManager.isFinished) {
            initModel()
            camController!!.modelInstance = mapInstance
            camController!!.addObserver { newValue -> observer(newValue) }


            modelBatch!!.begin(cam)
            modelBatch!!.render(mapInstance!!, environment)
            modelBatch!!.end()
        }
        else {
            spriteBatch!!.begin()
            font!!.draw(spriteBatch, "Map Loading...", (Gdx.graphics.width.toFloat() - font!!.region.regionWidth) / 3, (Gdx.graphics.height.toFloat() - font!!.region.regionHeight) / 1.75f)
            spriteBatch!!.end()
        }
    }

    override fun resize(width: Int, height: Int) {
    }

    override fun pause() {
    }

    override fun resume() {
    }

    override fun dispose() {
        if (modelBatch != null) {
            modelBatch!!.dispose()
        }
        if (bodyModel != null) {
            bodyModel!!.dispose()
        }
        font!!.dispose()
        spriteBatch!!.dispose()
    }

}
