package net.runelite.client.plugins.npcspawns;

import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import mapped.util.RSPSConstants;
import net.runelite.api.*;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.client.RuneLiteProperties;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.rs.ClientConfigLoader;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ImageUtil;

import javax.inject.Inject;
import javax.inject.Singleton;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Set;

@PluginDescriptor(
		name = "NPC Spawn Editor",
		description = "Edit NPC spawns",
		tags = {"tool", "spawn", "npcs"},
		enabledByDefault = false,
		developerPlugin = true
)
@Slf4j
@Singleton
public class NpcSpawnsPlugin extends Plugin {

	@Inject
	private Client client;

	@Inject
	private ClientThread clientThread;

	@Inject
	private ClientToolbar clientToolbar;

	@Inject
	private KeyManager keyManager;

	@Inject
	private NpcSpawnConfig config;

	@Inject
	private EventBus eventbus;

	private NpcSpawnsPanel uiPanel;

	private static final String WALK_HERE = "Walk here";
	// Option added to NPC menu
	private static final String TAG = "Remove NPC";
	private static final String SPAWN = "Spawn NPC";
	private NavigationButton uiNavigationButton;

	@Provides
	NpcSpawnConfig getConfig(ConfigManager configManager) {
		return configManager.getConfig(NpcSpawnConfig.class);
	}

	@Override
	protected void startUp() throws Exception {
		if (RuneLiteProperties.getLocalEnabled()) {
			final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "npc.png");
			uiPanel = injector.getInstance(NpcSpawnsPanel.class);

			uiNavigationButton = NavigationButton.builder()
					.tooltip("NPC Spawns")
					.icon(icon)
					.priority(6)
					.panel(uiPanel)
					.build();

			clientToolbar.addNavigation(uiNavigationButton);
			updateConfig();
		}
	}

	@Override
	protected void shutDown() throws Exception {
		eventbus.unregister(this);
		clientToolbar.removeNavigation(uiNavigationButton);
	}

	@Subscribe
	private void onConfigChanged(ConfigChanged configChanged) {
		if (!configChanged.getGroup().equals("npcspawneditor")) {
			return;
		}
		updateConfig();
	}

	@Subscribe
	private void onMenuEntryAdded(MenuEntryAdded event) {
		if (RuneLiteProperties.getLocalEnabled()) {
			int type = event.getType();

			if (type >= MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET) {
				type -= MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET;
			}

			if (client.isKeyPressed(KeyCode.KC_SHIFT) && event.getOption().equals(WALK_HERE)) {
				final Tile selectedSceneTile = client.getSelectedSceneTile();

				if (selectedSceneTile == null) {
					return;
				}


				final Tile tile = client.getSelectedSceneTile();
				if (tile == null) {
					return;
				}
				client.createMenuEntry(-1)
						.setParam0(event.getActionParam0())
						.setParam1(event.getActionParam1())
						.setTarget(event.getTarget())
						.setOption(SPAWN)
						.setType(MenuAction.RUNELITE)
						.setIdentifier(event.getIdentifier());
			} else if (client.isKeyPressed(KeyCode.KC_SHIFT) && type == MenuAction.EXAMINE_NPC.getId()) {
				// Add tag option
				client.createMenuEntry(-1)
						.setParam0(event.getActionParam0())
						.setParam1(event.getActionParam1())
						.setTarget(event.getTarget())
						.setOption(TAG)
						.setType(MenuAction.RUNELITE)
						.setIdentifier(event.getIdentifier());
			}
		}
	}

	@Subscribe
	private void onMenuOptionClicked(MenuOptionClicked click) {
		if (RuneLiteProperties.getLocalEnabled()) {
			if (click.getMenuAction() == MenuAction.RUNELITE && (click.getMenuOption().equals(SPAWN))) {
				Tile target = client.getSelectedSceneTile();

				if (target == null) {
					return;
				}
				WorldPoint worldPoint = target.getWorldLocation();
				int npcId = uiPanel.getNpcId();
				int walkRange = uiPanel.getWalkRange();
				String direction = uiPanel.getDirection();
				String command = String.format("::addspawn %d %d %d %d %s", npcId, walkRange, worldPoint.getX(), worldPoint.getY(), direction);
				client.addChatMessage(ChatMessageType.CONSOLE, "", command, "RL+");

				client.runScript(ScriptID.CHAT_SEND, ChatMessageType.PUBLICCHAT, command);
				click.consume();
				return;
			}
			if (click.getMenuAction() == MenuAction.RUNELITE && (click.getMenuOption().equals(TAG))) {
				final int id = click.getId();
				final NPC[] cachedNPCs = client.getCachedNPCs();
				final NPC npc = cachedNPCs[id];

				if (npc == null) {
					return;
				}

				String command = "::removespawn " + id;
				client.runScript(ScriptID.CHAT_SEND, ChatMessageType.PUBLICCHAT, command);
				click.consume();
				return;
			}
		}


	}

	private File spawnsFolder;

	private void updateConfig() {
		this.spawnsFolder = new File(config.outputLocation());
	}

}
