package ice.library.content.blocks.liquid

import arc.func.Func
import arc.func.Prov
import arc.graphics.Color
import arc.scene.ui.layout.Table
import arc.struct.OrderedMap
import arc.util.io.Reads
import arc.util.io.Writes
import ice.library.content.blocks.abstractBlocks.IceBlock
import ice.library.draw.drawer.DrawBuild
import ice.library.draw.drawer.DrawMulti
import mindustry.Vars
import mindustry.gen.Building
import mindustry.graphics.Pal
import mindustry.type.Liquid
import mindustry.ui.Bar
import mindustry.world.blocks.liquid.LiquidBlock
import mindustry.world.draw.DrawRegion
import mindustry.world.meta.BlockGroup
import kotlin.math.min

open class MultipleLiquidBlock(name: String) : IceBlock(name) {

    init {
        update = true
        hasLiquids = true
        outputsLiquid = false
        group = BlockGroup.liquids
        buildType = Prov(::MultipleBlockBuild)
        drawers = DrawMulti(DrawRegion("-bottom"), DrawBuild<MultipleBlockBuild> {
            if (liquid != null) {
                LiquidBlock.drawTiledFrames(size, x, y, 0f, 0f, 0f, 0f, liquid, liquids.get(liquid) / liquidCapacity)
            }
        }, DrawRegion("-top"))
    }

    inner class MultipleBlockBuild : IceBuild() {
        private var icebarMap: OrderedMap<String, Func<MultipleBlockBuild, Bar>> = OrderedMap()
        var liquid: Liquid? = null
        override fun acceptLiquid(source: Building, liquid: Liquid): Boolean {
            this.liquid = liquid
            return liquids.get(liquid) < liquidCapacity
        }

        override fun transferLiquid(next: Building, amount: Float, liquid: Liquid?) {
            val flow = min(liquids.get(liquid), min(next.block.liquidCapacity - next.liquids[liquid], amount))
            if (next.acceptLiquid(this, liquid)) {
                next.handleLiquid(this, liquid, flow)
                liquids.remove(liquid, flow)
            }
        }

        override fun drawSelect() {
            icebarMap.clear()
            iceAddBar("health") { entity: Building ->
                Bar("stat.health", Pal.health) { entity.healthf() }.blink(Color.white)
            }
            liquids.each { liquid, amount ->
                if (amount < 1) icebarMap.remove("liquid-" + liquid.name)
                if (amount > 1 && !icebarMap.containsKey("liquid-" + liquid.name)) addLiquidBar(liquid)
            }
            super.drawSelect()
        }

        private fun addLiquidBar(liquid: Liquid) {
            iceAddBar("liquid-" + liquid.name) { entity: Building ->
                if (!liquid.unlockedNow()) null else Bar({ liquid.localizedName }, { liquid.barColor() },
                    { entity.liquids.get(liquid) / liquidCapacity })
            }
        }

        private fun iceAddBar(name: String, sup: Func<MultipleBlockBuild, Bar>) {
            icebarMap.put(name, sup)
        }

        override fun displayBars(table: Table) {
            for (bar: Func<MultipleBlockBuild, Bar> in icebarMap.values()) {
                table.add(bar.get(this)).growX().row()
            }
        }

        override fun read(read: Reads, revision: Byte) {
            super.read(read, revision)
            val i: Int = read.i()
            liquid = if (i != -1) {
                Vars.content.liquid(i)
            } else {
                null
            }
        }

        override fun write(write: Writes) {
            super.write(write)
            if (liquid != null) {
                write.i(liquid!!.id.toInt())
            } else {
                write.i(-1)
            }
        }
    }
}

