/*
 *   This file is a part of the SteamWar software.
 *
 *   Copyright (C) 2025 SteamWar.de-Serverteam
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program 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 Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.bausystem.features.countingwand;

import de.steamwar.bausystem.BauSystem;
import de.steamwar.bausystem.region.Point;
import de.steamwar.bausystem.shared.Pair;
import de.steamwar.bausystem.utils.ItemUtils;
import de.steamwar.inventory.SWItem;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


@UtilityClass
public class Countingwand {

	public static ItemStack getWandItem(Player player) {
		ItemStack itemStack = new SWItem(Material.STICK, BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE1", player), BauSystem.MESSAGE.parse("COUNTINGWAND_ITEM_LORE2", player)), false, null).getItemStack();
		ItemUtils.setItem(itemStack, "countingwand");
		ItemMeta itemMeta = itemStack.getItemMeta();
		itemMeta.setCustomModelData(1);
		itemStack.setItemMeta(itemMeta);
		return itemStack;
	}

	private final Map<String, Pair<Point, Point>> selections = new HashMap<>();

	public boolean isCountingwand(ItemStack itemStack) {
		return ItemUtils.isItem(itemStack, "countingwand");
	}

	public void checkSelection(final Point point, final boolean pos1, final Player p) {
		Pair<Point, Point> selection = selections.get(p.getUniqueId().toString());
		final boolean newPos;
		if (selection != null) {
			if (pos1) {
				newPos = !point.equals(selection.setKey(point));
			} else {
				newPos = !point.equals(selection.setValue(point));
			}
		} else {
			if (pos1) {
				selection = new Pair<>(point, null);
			} else {
				selection = new Pair<>(null, point);
			}
			selections.put(p.getUniqueId().toString(), selection);
			newPos = true;
		}

		if (newPos) {
			String dimension = getDimensions(p, selection.getKey(), selection.getValue());
			String volume = getVolume(p, selection.getKey(), selection.getValue());
			if (pos1) {
				BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_RCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
			} else {
				BauSystem.MESSAGE.send("COUNTINGWAND_MESSAGE_LCLICK", p, point.getX(), point.getY(), point.getZ(), dimension, volume);
			}
		}
	}

	public void removePlayer(Player p) {
		selections.remove(p.getUniqueId().toString());
	}

	public String getVolume(Player player, final Point point1, final Point point2) {
		if (point1 == null || point2 == null) {
			return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, 0);
		}
		return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_VOLUME", player, getAmount(point1, point2));
	}

	public String getDimensions(Player player, final Point point1, final Point point2) {
		if (point1 == null || point2 == null) {
			return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, 0, 0, 0);
		}
		return BauSystem.MESSAGE.parse("COUNTINGWAND_MESSAGE_DIMENSION", player, Math.abs(point1.getX() - point2.getX()) + 1, Math.abs(point1.getY() - point2.getY()) + 1, Math.abs(point1.getZ() - point2.getZ()) + 1);
	}

	public int getAmount(final Point point1, final Point point2) {
		return (Math.abs(point1.getX() - point2.getX()) + 1) * (Math.abs(point1.getY() - point2.getY()) + 1) * (Math.abs(point1.getZ() - point2.getZ()) + 1);
	}
}