package net.taehui.twilight.note

import net.taehui.twilight.Component
import net.taehui.twilight.awilight.DefaultCompute
import net.taehui.twilight.note.JudgedNoteData.ID

class LongNote(logicalY: Double, wait: Double, input: Int, longWait: Double, longHeight: Double) :
    InputNote(logicalY, wait, input) {
    override val logicalLayer: Int
        get() = 2

    init {
        this.longWait = longWait
        this.longHeight = longHeight
    }

    override fun isTooLong(wait: Double, judgmentStage: Double): Boolean {
        return wait - (wait + longWait) >= Component.getJudgmentMillis(
            Component.Judged.LOWEST,
            judgmentStage,
            1,
            Component.JudgmentAssist.LONG_NOTE_UP
        )
    }

    override fun judge(input: Int, wait: Double, judgmentStage: Double, isAutoLongNote: Boolean): JudgedNoteData? {
        if (input > 0) {
            if (judged == Component.Judged.NOT) {
                val judgmentMeter = wait - this.wait
                val judged = Component.getJudged(judgmentMeter, judgmentStage, Component.JudgmentAssist.DEFAULT)
                if (judged != Component.Judged.NOT) {
                    return JudgedNoteData(ID.LEVY_LONG_NOTE_JUDGMENT, judgmentMeter, judged)
                }
            }
        } else if (judged != Component.Judged.NOT) {
            val longJudgmentMeter = wait - (this.wait + longWait)
            return if (isAutoLongNote) {
                if (Component.getIsJudgment(
                        longJudgmentMeter,
                        Component.Judged.LOWER,
                        judgmentStage,
                        Component.JudgmentAssist.LONG_NOTE_UP
                    )
                ) {
                    JudgedNoteData(
                        ID.AUTO_LONG_NOTE_JUDGMENT,
                        0.0,
                        Component.Judged.HIGHEST
                    )
                } else JudgedNoteData(
                    ID.FAILED_LONG_NOTE_JUDGMENT,
                    0.0,
                    Component.Judged.HIGHEST
                )
            } else {
                val judged =
                    Component.getJudged(longJudgmentMeter, judgmentStage, Component.JudgmentAssist.LONG_NOTE_UP)
                if (judged != Component.Judged.NOT) {
                    JudgedNoteData(ID.QUIT_LONG_NOTE_JUDGMENT, longJudgmentMeter, judged)
                } else {
                    JudgedNoteData(ID.FAILED_LONG_NOTE_JUDGMENT, 0.0, judged)
                }
            }
        }
        return null
    }

    override fun paint(defaultComputer: DefaultCompute) {
        val multiplier = defaultComputer.modeComponentValue.getPaidMultiplier()
        if (multiplier > 0.0) {
            val y = getY(multiplier)
            val pointHeight = longHeight * multiplier
            val position0 = (input - 1) * NOTE_LENGTH
            val position1 = y - pointHeight
            var longNoteContentsHeight = pointHeight
            if (!isFailed && judged != Component.Judged.NOT) {
                val longHeight = pointHeight - y + Component.STANDARD_HEIGHT
                if (longHeight > 0.0) {
                    longNoteContentsHeight += longHeight - pointHeight
                    if (longNoteContentsHeight > 0.0) {
                        if (position1 + longNoteContentsHeight > 0.0) {
                            defaultComputer.netDrawings.add(
                                EventOuterClass.Event.NetDrawing.newBuilder().apply {
                                    this.drawingVariety = EventOuterClass.Event.NetDrawing.Variety.Note
                                    this.param = Component.NET_DRAWINGS[defaultComputer.inputMode.value]!![input]
                                    this.position0 = position0
                                    this.position1 = position1
                                    this.length = NOTE_LENGTH
                                    this.height = longNoteContentsHeight
                                }.build()
                            )
                        }
                    }
                }
            } else {
                if (longNoteContentsHeight > 0.0) {
                    if (position1 + longNoteContentsHeight > 0.0) {
                        defaultComputer.netDrawings.add(
                            EventOuterClass.Event.NetDrawing.newBuilder().apply {
                                this.drawingVariety = EventOuterClass.Event.NetDrawing.Variety.Note
                                this.param = Component.NET_DRAWINGS[defaultComputer.inputMode.value]!![input]
                                this.position0 = position0
                                this.position1 = position1
                                this.length = NOTE_LENGTH
                                this.height = longNoteContentsHeight
                            }.build()
                        )
                    }
                }
            }
        }
    }
}