/*
 * This file is part of LiquidBounce (https://github.com/CCBlueX/LiquidBounce)
 *
 * Copyright (c) 2015 - 2025 CCBlueX
 *
 * LiquidBounce is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LiquidBounce is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LiquidBounce. If not, see <https://www.gnu.org/licenses/>.
 */
package net.ccbluex.liquidbounce.features.module.modules.exploit.disabler.disablers

import net.ccbluex.liquidbounce.config.types.nesting.ToggleableConfigurable
import net.ccbluex.liquidbounce.event.events.PacketEvent
import net.ccbluex.liquidbounce.event.events.TransferOrigin
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.modules.exploit.disabler.ModuleDisabler
import net.ccbluex.liquidbounce.utils.client.isOlderThanOrEqual1_8
import net.minecraft.network.packet.Packet
import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket
import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket
import net.minecraft.util.Hand

/**
 * This fixes the order of the swing packet when placing, breaking or attacking blocks.
 * Use this if you have problems with NoSwing flags.
 *
 * On outdated anti-cheats such as NoCheatPlus this is required, otherwise you will get flagged for NoSwing.
 * On newer anti-cheats this is not required AND SHOULD NOT BE USED AS IT WILL CHANGE THE ORDER OF THE SWING PACKET.
 */
internal object DisablerSwingOrder : ToggleableConfigurable(ModuleDisabler, "SwingOrder", false) {

    private var previousPacket: Packet<*>? = null
    private var fixedThis = false

    override fun onEnabled() {
        previousPacket = null
        super.onEnabled()
    }

    val packetHandler = handler<PacketEvent> { event ->
        if (event.origin != TransferOrigin.OUTGOING) {
            return@handler
        }

        // If this is true, we are already using a fixed variant
        if (isOlderThanOrEqual1_8) {
            return@handler
        }

        val packet = event.packet

        when (packet) {

            is PlayerInteractBlockC2SPacket -> {
                if (previousPacket !is HandSwingC2SPacket) {
                    network.sendPacket(HandSwingC2SPacket(packet.hand))

                    // Since we sent a swing packet already, we need to prevent sending another next
                    fixedThis = true
                }
            }

            is PlayerInteractEntityC2SPacket -> {
                if (previousPacket !is HandSwingC2SPacket) {
                    network.sendPacket(HandSwingC2SPacket(Hand.MAIN_HAND))

                    // Since we sent a swing packet already, we need to prevent sending another next
                    fixedThis = true
                }
            }

            is HandSwingC2SPacket -> {
                if (fixedThis) {
                    event.cancelEvent()
                    fixedThis = false
                }
            }
        }

        previousPacket = packet
    }

}
