package net.touhoudiscord.hexucasting.common.casting.actions.spells

import at.petrak.hexcasting.api.misc.MediaConstants
import at.petrak.hexcasting.api.spell.*
import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.iota.Iota
import at.petrak.hexcasting.xplat.IXplatAbstractions
import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.phys.Vec3
import net.touhoudiscord.hexucasting.api.config.HexucastingConfig
import net.touhoudiscord.hexucasting.common.casting.actions.OpExampleConstMediaAction.argc

object OpDaylightAction : SpellAction {
	/**
	 * The number of arguments from the stack that this action requires.
	 */
	override val argc = 1

	/**
	 * The method called when this Action is actually executed. Accepts the [args]
	 * that were on the stack (there will be [argc] of them), and the [ctx],
	 * which contains things like references to the caster, the ServerLevel,
	 * methods to determine whether locations and entities are in ambit, etc.
	 * Returns a triple of things. The [RenderedSpell] is responsible for the spell actually
	 * doing things in the world, the [Int] is how much media the spell should cost,
	 * and the [List] of [ParticleSpray] renders particle effects for the result of the SpellAction.
	 *
	 * The [execute] method should only contain code to find the targets of the spell and validate
	 * them. All the code that actually makes changes to the world (breaking blocks, teleporting things,
	 * etc.) should be in the private [Spell] data class below.
	 */
	override fun execute(args: List<Iota>, ctx: CastingContext): Triple<RenderedSpell, Int, List<ParticleSpray>> {
		val time = minOf(args.getPositiveInt(0, argc), 24000)

		return Triple(
			Spell(time),
			MediaConstants.CRYSTAL_UNIT*2,
			listOf()
		)
	}

	/**
	 * This class is responsible for actually making changes to the world. It accepts parameters to
	 * define where/what it should affect (for this example the parameter is [vec]), and the
	 * [cast] method within is responsible for using that data to alter the world.
	 */
	private data class Spell(val time: Int) : RenderedSpell {
		override fun cast(ctx: CastingContext) {
			val w = ctx.world
			val relativeTime = w.dayTime%24000
			if (relativeTime > time) {
				w.dayTime += 24000
			}
			w.dayTime = w.dayTime-relativeTime+time
		}
	}
}