import com.dowstats.configuration.StorageConfig
import com.dowstats.service.w40k.IconsService
import org.junit.jupiter.api.Test
import java.awt.image.BufferedImage
import java.io.File
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
import javax.imageio.ImageIO


class RtxConvertScript {

    val headersAndTypesByteSize = 20

    var imageBytes: List<Byte> = emptyList()
    var width: Int = 0
    var height: Int = 0
    var format: Int = 0
    var numMips: Int = 0

    val iconsService = IconsService(StorageConfig())


    @Test
    fun convertAllRtx(){
        val folder = "E:\\home\\cnb\\wanila\\art\\ui\\ingame"
        File(folder).walkTopDown().map {fileOrFolder ->
            if(fileOrFolder.isFile && fileOrFolder.name.endsWith(".dds") ){
                try {
                    convertFile(fileOrFolder.path)
                } catch (e: Exception) {
                    println(e.message)
                }

            }   else {
                null
            }

        }.toList()
    }


    fun convertFile(fileName: String) {

        convertRtx(fileName)
        /*val file = fileName
        val data = File(file).readBytes().toList()

        getDDSHeader()
        File(fileName.replace(".rtx", ".dds")).writeBytes((getDDSHeader() + data.drop(128)).toByteArray())*/
        iconsService.convertTgaToJpegImage(fileName,  File(fileName).path, "Converted", true)

        val image = ImageIO.read(File(fileName.replace(".rtx", ".tga")))

        val outputImage = BufferedImage(image.height, image.width, image.type)

        val g2d = outputImage.createGraphics()
        g2d.rotate(Math.toRadians(180.0), (image.width / 2).toDouble(), (image.height / 2).toDouble())
        g2d.drawImage(image, 0 + image.width, 0, -image.width, image.height, null)
        g2d.dispose()

        ImageIO.write(outputImage, "tga", File(fileName.replace(".dds", ".tga")));

    }

    fun getDDSHeader(): List<Byte> {
        val _DOW_DXT_FLAGS = 0x000A1007
        val _ddsF_FOURCC = 0x00000004
        val _DOW_DDSCAPS_FLAGS = 0x401008
        val signature = "DDS ".toByteArray(Charsets.US_ASCII)
        signature + ByteBuffer.allocate(4).putInt(124).array()
        val fourCC = when(format) {
            8 -> "DXT1"
            10 -> "DXT3"
            11 -> "DXT5"
            else -> "----"
        }.toByteArray(Charsets.US_ASCII)
        return (signature + to32Bit(124) + to32Bit(_DOW_DXT_FLAGS) + to32Bit(height) + to32Bit(width) + to32Bit(imageBytes.size) + to32Bit(0) + to32Bit(numMips)
                + ByteBuffer.allocate(44).array() + to32Bit(32) + to32Bit(_ddsF_FOURCC) + fourCC
                + ByteBuffer.allocate(20).array() + to32Bit(_DOW_DDSCAPS_FLAGS) + ByteBuffer.allocate(16).array()).toList()
    }

    fun to32Bit(i: Int): List<Byte> {
        return ByteBuffer.allocate(4).putInt(i).array().reversed()
    }

    private fun convertRtx(fileName: String) {

        File(fileName).readBytes().size
        var byteArrayParse = File(fileName).readBytes().toList().drop(24)

        readHeader(byteArrayParse)

    }

    private fun readHeader(bytes: List<Byte>, lvl: Int = 0): Int{
        val type1 = String(bytes.take(4).toByteArray(), StandardCharsets.UTF_8)
        val type2 = String(bytes.subList(4, 8).toByteArray(), StandardCharsets.UTF_8)

        val arrSize = bytes.subList(8, 12).reversed().toByteArray().getUIntAt(0)
        val bytesSize = bytes.subList(12, 16).reversed().toByteArray().getUIntAt(0)
        val headerValueSize = bytes.subList(16, 20).reversed().toByteArray().getUIntAt(0)

        val header = String(bytes.subList(headersAndTypesByteSize, headersAndTypesByteSize + headerValueSize.toInt()).toByteArray(), StandardCharsets.UTF_8)

        val dataBytes = bytes.subList(headersAndTypesByteSize + headerValueSize.toInt(), headersAndTypesByteSize + headerValueSize.toInt() + bytesSize.toInt())

        println("Type1: $type1, Type2: $type2, ArrSize: $arrSize BytesSize: $bytesSize HeaderValueSize: $headerValueSize Header: $header Bytes: ${dataBytes.size}")

        var i = 0
        if(type1 == "FOLD") {
            while (i < bytesSize.toInt()){
                val bytesSublist = bytes.subList(headersAndTypesByteSize + headerValueSize.toInt() + i, headersAndTypesByteSize + headerValueSize.toInt()  + bytesSize.toInt())
                i += readHeader(bytesSublist, lvl + 1)
            }
        }
        if(type2 == "ATTR"){
            format = dataBytes.take(4).reversed().toByteArray().getUIntAt(0).toInt()
            width = dataBytes.subList(4,8).reversed().toByteArray().getUIntAt(0).toInt()
            height = dataBytes.subList(8,12).reversed().toByteArray().getUIntAt(0).toInt()
            numMips = dataBytes.subList(12,16).reversed().toByteArray().getUIntAt(0).toInt()
            println("Format: $format, Width: $width, Height: $height, NumMips: $numMips")
        }
        if(type2 == "DATA"){
            imageBytes = dataBytes
        }
        return bytesSize.toInt() + headersAndTypesByteSize
    }









    private fun ByteArray.getUIntAt(idx: Int): UInt =
        ((this[idx].toUInt() and 0xFFu) shl 24) or
                ((this[idx + 1].toUInt() and 0xFFu) shl 16) or
                ((this[idx + 2].toUInt() and 0xFFu) shl 8) or
                (this[idx + 3].toUInt() and 0xFFu)

}