package ru.dbotthepony.mc.otm.server.command

import net.minecraft.commands.Commands
import net.minecraft.commands.arguments.EntityArgument
import net.minecraft.world.entity.player.Player
import net.neoforged.neoforge.event.RegisterCommandsEvent
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.capability.matteryPlayer

object AndroidCommand {
	fun register(event: RegisterCommandsEvent) {
		event.dispatcher.register(
			Commands.literal("android")
				.requires { it.hasPermission(Commands.LEVEL_GAMEMASTERS) }
				.then(Commands.literal("on")
					.executes { makeAndroid(listOf(it.source.playerOrException)) }
					.then(Commands.argument("targets", EntityArgument.players()).executes { makeAndroid(EntityArgument.getPlayers(it, "targets")) })
				)
				.then(Commands.literal("off")
					.executes { makeHuman(listOf(it.source.playerOrException)) }
					.then(Commands.argument("targets", EntityArgument.players()).executes { makeHuman(EntityArgument.getPlayers(it, "targets")) })
				)
				.then(
					Commands.literal("research")
					.then(
						Commands.literal("grant")
						.then(
							Commands.argument("targets", EntityArgument.players())
							.then(
								Commands.argument("research", AndroidResearchArgument.create())
								.executes {
									grantResearch(EntityArgument.getPlayers(it, "targets"), AndroidResearchArgument.getResearchType(it, "research"))
								}
								.then(
									Commands.literal("force")
									.executes {
										grantResearch(EntityArgument.getPlayers(it, "targets"), AndroidResearchArgument.getResearchType(it, "research"), true)
									}
								)
							)
							.then(
								Commands.literal("*")
								.executes {
									val players = EntityArgument.getPlayers(it, "targets")
									AndroidResearchManager.researchMap.map { a -> a.value }.forEach { a ->
										grantResearch(players, a)
									}

									players.size
								}
								.then(
									Commands.literal("force")
									.executes {
										val players = EntityArgument.getPlayers(it, "targets")
										AndroidResearchManager.researchMap.map { a -> a.value }.forEach { a ->
											grantResearch(players, a, true)
										}

										players.size
									}
								)
							)
						)
					)
					.then(
						Commands.literal("revoke")
						.then(
							Commands.argument("targets", EntityArgument.players())
							.then(
								Commands.argument("research", AndroidResearchArgument.create())
								.executes {
									revokeResearch(EntityArgument.getPlayers(it, "targets"), AndroidResearchArgument.getResearchType(it, "research"))
								}
							)
							.then(
								Commands.literal("*")
								.executes {
									val players = EntityArgument.getPlayers(it, "targets")
									AndroidResearchManager.researchMap.map { a -> a.value }.forEach { a ->
										revokeResearch(players, a)
									}

									players.size
								}
							)
						)

					)
			)
		)
	}

	private fun grantResearch(players: Collection<Player>, type: AndroidResearchType, force: Boolean = false): Int {
		for (player in players) {
			player.matteryPlayer.getResearch(type).research(force, free = true)
		}

		return players.size
	}

	private fun revokeResearch(players: Collection<Player>, type: AndroidResearchType): Int {
		for (player in players) {
			player.matteryPlayer.getResearch(type).unResearch()
		}

		return players.size
	}

	private fun makeAndroid(players: Collection<Player>): Int {
		for (player in players) {
			player.matteryPlayer.becomeAndroid()
		}

		return players.size
	}

	private fun makeHuman(players: Collection<Player>): Int {
		for (player in players) {
			player.matteryPlayer.becomeHumane()
		}

		return players.size
	}
}
