package ru.dbotthepony.mc.otm.android.feature

import net.minecraft.network.FriendlyByteBuf
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.capability.energy.extractEnergyExact
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.client.render.MGUIGraphics
import ru.dbotthepony.mc.otm.client.render.ResearchIcons
import ru.dbotthepony.mc.otm.config.AndroidConfig
import ru.dbotthepony.mc.otm.config.ClientConfig
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.network.GenericNetworkChannel
import ru.dbotthepony.mc.otm.network.MNetworkContext
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel
import ru.dbotthepony.mc.otm.network.SmokeParticlesPacket
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import ru.dbotthepony.mc.otm.registry.MSoundEvents

object TriggerJumpBoostPacket : MatteryPacket {
	override fun write(buff: FriendlyByteBuf) {
		// no op
	}

	override fun play(context: MNetworkContext) {
		val mattery = context.sender?.matteryPlayer ?: return

		if (!mattery.isAndroid)
			return

		val feature = mattery.getFeature(AndroidFeatures.JUMP_BOOST) ?: return

		if (feature.isActive && feature.cooldown <= 4 && mattery.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, false)) {
			feature.putOnCooldown()

			context.sender.level.playSound(
				context.sender, context.sender,
				MSoundEvents.ANDROID_JUMP_BOOST, SoundSource.PLAYERS,
				1f, 1f
			)

			GenericNetworkChannel.makeSmoke(context.sender, context.sender.x, context.sender.y, context.sender.z)
		}
	}
}

class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.JUMP_BOOST, capability) {
	private var tickCooldownClient = false

	override val maxCooldown: Int
		get() = (AndroidConfig.JumpBoost.BASE_COOLDOWN - AndroidConfig.JumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0)

	override var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote ->
		access.write(value)

		if (setByRemote) {
			tickCooldownClient = false
		}
	}).property

	private var lastGround = false

	fun movementTick(isJumping: Boolean, isShifting: Boolean) {
		check(ply !is ServerPlayer) { "Invalid side" }

		if (ply.isSpectator) {
			return
		}

		val old = lastGround
		lastGround = ply.isOnGround

		if (isActive && cooldown <= 0 && old != lastGround && !lastGround && isJumping && isShifting && ply.xRot <= ClientConfig.JUMP_BOOST_LOOK_ANGLE && android.androidEnergy.extractEnergyExact(AndroidConfig.JumpBoost.ENERGY_COST, true)) {
			ply.deltaMovement += Vector(0.0, AndroidConfig.JumpBoost.POWER * (level + 1) / 20.0, 0.0)
			putOnCooldown()
			MatteryPlayerNetworkChannel.sendToServer(TriggerJumpBoostPacket)

			ply.level.playSound(
				ply, ply,
				MSoundEvents.ANDROID_JUMP_BOOST, SoundSource.PLAYERS,
				1f, 1f
			)

			SmokeParticlesPacket.makeSmoke(ply.x, ply.y, ply.z, ply.random, ply.level)
		}
	}

	override fun tickClient() {
		if (tickCooldownClient && cooldown > 0) {
			cooldown--
		}
	}

	override fun renderIcon(graphics: MGUIGraphics, x: Float, y: Float, width: Float, height: Float, color: RGBAColor) {
		ResearchIcons.ICON_JUMP_BOOST.render(graphics, x, y, width, height, color = if (cooldown > 0) color * RGBAColor.REDDISH else color)
	}
}
