import { EntityComponentTypes, system } from "@minecraft/server"
import { ActionFormData, ModalFormData } from "@minecraft/server-ui"

const pages = [
	"Introduction",
	"Instruction",
	"Capture Net",
	"Chicken Nest",
	"Egg Collector",
	"Egg Processor",
	"Chicken Breeder",
	"Grass, Dirt",
	"Oak Log, Pale Log",
	"Coal, Flint",
	"Deepslate, Gravel",
	"String, Feather",
	"Leather, Granite",
	"Diorite, Andesite",
	"Cobblestone, Sand",
	"Red Sand, Clay",
	"Tuff, Bread",
	"Potato, Carrot",
	"Beetroot, Red Mushroom",
	"Brown, Mushroom Mud",
	"Snow, Warped Stem",
	"Crimson Stem, Warped Fungus",
	"Crimson Fungus, Water",
	"Prismarine Shard, Prismarine Crystal",
	"Ink Sac, Sandstone",
	"Red Sandstone, Netherrack",
	"Basalt, Blackstone",
	"Jungle Log, Copper Ingot",
	"Lapis Lazuli, Redstone Dust",
	"Acacia Log, Dark Oak Log",
	"Golden Carrot, Sweet Berries",
	"Glow Berries, Cocoa Beans",
	"Pumpkin, Melon Slice",
	"Stone, Ice",
	"Calcite, Glass",
	"Cactus, Sugar Cane",
	"Soul Sand, Chorus Fruit",
	"Nether Wart, Gilded Blackstone",
	"Apple, Glow Ink Sac",
	"End Stone, Lava",
	"Bone, Warped Nylium",
	"Crimson Nylium, Charcoal",
	"Emerald, Obsidian",
	"Cherry Log",
	"Golden Apple, Mangrove Log",
	"Heart of the Sea, Eye of Ender",
	"Slimeball",
	"Sponge",
	"Gold Ingot",
	"Blaze Rod",
	"Enderpearl",
	"Sea Lantern",
	"Echo Shard, Amethyst Shard",
	"Crying Obsidian, Nether Quartz",
	"Glowstone, Magma",
	"Iron Ingot",
	"Diamond",
	"Netherite Ingot",
	"Enchanted Golden Apple",
	"Bottle of Enchanting",
	"Dragon Egg",
	"Dragon Breath",
	"Shulker Shell",
	"Totem of Undying",
	"Nether Star",
	"Netherite Scrap"
]

export function spawnIntroductionBook(player) {
	player.dimension
		.getEntities({ type: "ds_mch:introduction_book" })
		.forEach(entity => {
			if (entity.getDynamicProperty("ds_mch:owner") === player.id)
				removeIntroductionBook(entity)
		})

	const book = player.dimension.spawnEntity("ds_mch:introduction_book", {
		x: player.location.x + player.getViewDirection().x * 2,
		y: player.location.y,
		z: player.location.z + player.getViewDirection().z * 2
	})
	const rotation = player.getRotation().y + 180
	book.setRotation({ x: 0, y: rotation })
	book.setDynamicProperty("ds_mch:owner", player.id)

	const { dimension, location } = book
	const rideableComponent = book.getComponent(EntityComponentTypes.Rideable)
	if (!rideableComponent) return

	const leftPage = dimension.spawnEntity("ds_mch:left_page", location)
	rideableComponent.addRider(leftPage)

	const rightPage = dimension.spawnEntity("ds_mch:right_page", location)
	rideableComponent.addRider(rightPage)

	const searchButton = dimension.spawnEntity("ds_mch:search_button", location)
	rideableComponent.addRider(searchButton)
}

export function previousPage(page) {
	const ridingComponent = page.getComponent(EntityComponentTypes.Riding)
	if (ridingComponent === undefined) return
	const book = ridingComponent.entityRidingOn
	if (book === undefined) return

	const previousPage = book.getProperty("ds_mch:page") - 1
	if (previousPage < 0) return

	book.dimension.playSound("item.book.page_turn", book.location)
	book.playAnimation("flip_back")
	system.runTimeout(() => book.setProperty("ds_mch:page", previousPage), 10)
}

export function nextPage(page) {
	const ridingComponent = page.getComponent(EntityComponentTypes.Riding)
	if (ridingComponent === undefined) return
	const book = ridingComponent.entityRidingOn
	if (book === undefined) return

	const nextPage = book.getProperty("ds_mch:page") + 1
	if (nextPage > 26) return

	book.dimension.playSound("item.book.page_turn", book.location)
	book.playAnimation("flip_forward")
	system.runTimeout(() => book.setProperty("ds_mch:page", nextPage), 10)
}

export function searchPage(button, player) {
	const ridingComponent = button.getComponent(EntityComponentTypes.Riding)
	if (ridingComponent === undefined) return
	const book = ridingComponent.entityRidingOn
	if (book === undefined) return

	const currentPage = book.getProperty("ds_mch:page")

	const searchMenu = new ModalFormData()
	searchMenu.title({ translate: "ds_mch:ui.search_menu.title" })
	searchMenu.textField(
		{ translate: "ds_mch:ui.search_menu.label" },
		{ translate: "ds_mch:ui.search_menu.placeholder" }
	)
	searchMenu.show(player).then(formData => {
		if (formData.formValues === undefined) return -1
		const input = formData.formValues[0]
		const query = input.trim().toLowerCase()
		const foundPageIndices = pages
			.map((page, index) => (page.toLowerCase().includes(query) ? index : -1))
			.filter(index => index !== -1)
		if (foundPageIndices.length == 0) {
			player.onScreenDisplay.setActionBar({
				translate: "ds_mch:ui.search_menu.no_pages_found",
				with: [input]
			})
			player.playSound("note.bass")
			return
		} else if (foundPageIndices.length == 1) {
			const foundPage = Math.floor(foundPageIndices[0] / 2)
			if (foundPage === currentPage) return

			book.dimension.playSound("item.book.page_turn", book.location)

			if (foundPage > currentPage) book.playAnimation("flip_forward")
			else book.playAnimation("flip_back")

			system.runTimeout(() => book.setProperty("ds_mch:page", foundPage), 10)
		} else {
			const resultMenu = new ActionFormData()
			resultMenu.title({ translate: "ds_mch:ui.result_menu.title" })
			foundPageIndices.forEach(foundPageIndex => {
				const foundPage = pages[foundPageIndex]
				resultMenu.button(foundPage)
			})
			resultMenu.show(player).then(formData => {
				if (formData.selection === undefined) return -1

				const index = formData.selection
				const foundPage = Math.floor(foundPageIndices[index] / 2)
				if (foundPage === currentPage) return

				book.dimension.playSound("item.book.page_turn", book.location)

				if (foundPage > currentPage) book.playAnimation("flip_forward")
				else book.playAnimation("flip_back")

				system.runTimeout(
					() =>
						book.setProperty(
							"ds_mch:page",
							Math.floor(foundPageIndices[index] / 2)
						),
					10
				)
			})
		}
	})
}

export function removeIntroductionBook(entity) {
	const rideableComponent = entity.getComponent(EntityComponentTypes.Rideable)
	if (rideableComponent) {
		rideableComponent.getRiders().forEach(rider => rider.remove())
	}
	const ridingComponent = entity.getComponent(EntityComponentTypes.Riding)
	if (ridingComponent) {
		const mount = ridingComponent.entityRidingOn
		const mountRideableComponent = mount.getComponent(
			EntityComponentTypes.Rideable
		)
		mountRideableComponent.getRiders().forEach(rider => rider.remove())
		mount.remove()
	}
	if (entity.isValid()) entity.remove()
}
