package mg.dot.feufaro.midi

import mg.dot.feufaro.solfa.ParseULine
import mg.dot.feufaro.solfa.Transpose


data class MidiPitch (
    var voiceNumber: Int = 0,
    var octave: Int = 0,
    var pitch: String = "",
    var alter: String = "",
    var duration: Int = 0,
    var markers: List<String> = listOf(),
    var tick : Int = 0,
    var metaBytes: ByteArray = byteArrayOf(),
    var metaByteSize: Int = 0,
    var metaType : Int = -1
) {
    var velocity: Int = 96
    companion object {
        var key: String = "C"
        var curVoiceNumber: Int = 0
        var nextTick : MutableList<Int> = mutableListOf()
    }
    fun setMeta(type: Int, tickMeta: Int, nb: Int, vararg data: Int) {
        val bytes = ByteArray(nb) { i ->
            (data.getOrElse(i) { 0 } and 0xFF).toByte()
        }
        metaBytes = bytes
        tick = tickMeta
        metaByteSize = nb
        metaType = type
    }
    fun setNote(note: String, theDuration: Int) {
        val midiPitch = Transpose.transposeToMidi(note, key, "C")
        velocity = if (midiPitch < 0) {
            0
        } else {
            99
        }
        pitch = midiPitch.toString()
        duration = theDuration
        tick = nextTick.getOrNull(voiceNumber) ?: 0
        nextTick[voiceNumber] = theDuration + tick
        voiceNumber = curVoiceNumber
        metaType = -1
    }
    fun setMarker(theMarkers : MutableList<String>) {
        if (theMarkers.isNotEmpty()) {
            markers = theMarkers.toList()
        } else {
            markers = listOf()
        }
    }
    fun currentVoiceNumber(value: Int) {
        curVoiceNumber = value
        while (nextTick.size <= value) {
            nextTick.add(0)
        }
    }
    fun initKey(theKey: String, isMinor: Boolean = false) {
        key = theKey
        val armature = Transpose.toArmature(theKey)

        val tickMeta = nextTick.getOrNull(0) ?: 0
        val mode = if (isMinor) 1 else 0
        setMeta(0x59, tickMeta, 2, armature, mode)
    }
    fun initMeasure(theMeasure: String): Boolean {
        val parts = theMeasure.split("/")
        val numerator = parts.getOrNull(0)?.toIntOrNull() ?: return false
        val denominator = parts.getOrNull(1)?.toIntOrNull() ?: 4

        val denomPower = when (denominator) {
            1 -> 0
            2 -> 1
            4 -> 2
            8 -> 3
            16 -> 4
            32 -> 5
            else -> 2
        }
        val tickMeta = nextTick.getOrNull(0) ?: 0
        setMeta(0x58, tickMeta, 4, numerator, denomPower, 24, 8)

        return true
    }
    fun reset() {
        tick = 0
        nextTick.clear()
    }
}