/*
 * Copyright © 2004-2026 L2J DataPack
 * 
 * This file is part of L2J DataPack.
 * 
 * L2J DataPack is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * L2J DataPack 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
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jserver.datapack.quests.Q00456_DontKnowDontCare;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.l2jserver.gameserver.datatables.ItemTable;
import com.l2jserver.gameserver.enums.QuestType;
import com.l2jserver.gameserver.enums.audio.Sound;
import com.l2jserver.gameserver.model.AggroInfo;
import com.l2jserver.gameserver.model.L2CommandChannel;
import com.l2jserver.gameserver.model.actor.L2Attackable;
import com.l2jserver.gameserver.model.actor.L2Npc;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.items.L2Item;
import com.l2jserver.gameserver.model.quest.Quest;
import com.l2jserver.gameserver.model.quest.QuestState;
import com.l2jserver.gameserver.model.quest.State;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.clientpackets.Say2;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.util.Util;

/**
 * Don't Know, Don't Care (456)
 * @author lion, ivantotov, jurchiks
 */
public final class Q00456_DontKnowDontCare extends Quest {
	// NPCs
	// @formatter:off
	private static final int[] SEPARATED_SOUL =
	{
		32864, 32865, 32866, 32867, 32868, 32869, 32870, 32891
	};
	// @formatter:on
	private static final int DRAKE_LORD_CORPSE = 32884;
	private static final int BEHEMOTH_LEADER_CORPSE = 32885;
	private static final int DRAGON_BEAST_CORPSE = 32886;
	// Items
	private static final int DRAKE_LORD_ESSENCE = 17251;
	private static final int BEHEMOTH_LEADER_ESSENCE = 17252;
	private static final int DRAGON_BEAST_ESSENCE = 17253;
	// Misc
	private static final int MIN_PLAYERS = 18;
	private static final int MIN_LEVEL = 80;
	private static final Map<Integer, Integer> MONSTER_NPCS = new HashMap<>();
	private static final Map<Integer, Integer> MONSTER_ESSENCES = new HashMap<>();
	private static final String TIMER_UNSPAWN_RAID_CORPSE = "TIMER_UNSPAWN_RAID_CORPSE";
	
	static {
		MONSTER_NPCS.put(25725, DRAKE_LORD_CORPSE);
		MONSTER_NPCS.put(25726, BEHEMOTH_LEADER_CORPSE);
		MONSTER_NPCS.put(25727, DRAGON_BEAST_CORPSE);
		MONSTER_ESSENCES.put(DRAKE_LORD_CORPSE, DRAKE_LORD_ESSENCE);
		MONSTER_ESSENCES.put(BEHEMOTH_LEADER_CORPSE, BEHEMOTH_LEADER_ESSENCE);
		MONSTER_ESSENCES.put(DRAGON_BEAST_CORPSE, DRAGON_BEAST_ESSENCE);
	}
	
	// Rewards
	private static final int[] WEAPONS = {
		15558, // Periel Sword
		15559, // Skull Edge
		15560, // Vigwik Axe
		15561, // Devilish Maul
		15562, // Feather Eye Blade
		15563, // Octo Claw
		15564, // Doubletop Spear
		15565, // Rising Star
		15566, // Black Visage
		15567, // Veniplant Sword
		15568, // Skull Carnium Bow
		15569, // Gemtail Rapier
		15570, // Finale Blade
		15571, // Dominion Crossbow
	};
	private static final int[] ARMOR = {
		15743, // Sealed Vorpal Helmet
		15746, // Sealed Vorpal Breastplate
		15749, // Sealed Vorpal Gaiters
		15752, // Sealed Vorpal Gauntlets
		15755, // Sealed Vorpal Boots
		15758, // Sealed Vorpal Shield
		15744, // Sealed Vorpal Leather Helmet
		15747, // Sealed Vorpal Leather Breastplate
		15750, // Sealed Vorpal Leather Leggings
		15753, // Sealed Vorpal Leather Gloves
		15756, // Sealed Vorpal Leather Boots
		15745, // Sealed Vorpal Circlet
		15748, // Sealed Vorpal Tunic
		15751, // Sealed Vorpal Stockings
		15754, // Sealed Vorpal Gloves
		15757, // Sealed Vorpal Shoes
		15759, // Sealed Vorpal Sigil
	};
	private static final int[] ACCESSORIES = {
		15763, // Sealed Vorpal Ring
		15764, // Sealed Vorpal Earring
		15765, // Sealed Vorpal Necklace
	};
	private static final int[] ATTRIBUTE_CRYSTALS = {
		9552, // Fire Crystal
		9553, // Water Crystal
		9554, // Earth Crystal
		9555, // Wind Crystal
		9556, // Dark Crystal
		9557, // Holy Crystal
	};
	private static final int BLESSED_SCROLL_ENCHANT_WEAPON_S = 6577;
	private static final int BLESSED_SCROLL_ENCHANT_ARMOR_S = 6578;
	private static final int SCROLL_ENCHANT_WEAPON_S = 959;
	private static final int GEMSTONE_S = 2134;
	private final Map<Integer, Set<Integer>> allowedPlayerMap = new ConcurrentHashMap<>();
	
	public Q00456_DontKnowDontCare() {
		super(456);
		bindStartNpc(SEPARATED_SOUL);
		bindTalk(SEPARATED_SOUL);
		bindFirstTalk(DRAKE_LORD_CORPSE, BEHEMOTH_LEADER_CORPSE, DRAGON_BEAST_CORPSE);
		bindTalk(DRAKE_LORD_CORPSE, BEHEMOTH_LEADER_CORPSE, DRAGON_BEAST_CORPSE);
		bindKill(MONSTER_NPCS.keySet());
		registerQuestItems(DRAKE_LORD_ESSENCE, BEHEMOTH_LEADER_ESSENCE, DRAGON_BEAST_ESSENCE);
	}
	
	@Override
	public String onFirstTalk(L2Npc npc, L2PcInstance player) {
		final QuestState qs = getQuestState(player, false);
		final Set<Integer> allowedPlayers = allowedPlayerMap.get(npc.getObjectId());
		
		if ((qs == null) || !qs.isCond(1) || (allowedPlayers == null) || !allowedPlayers.contains(player.getObjectId())) {
			return npc.getId() + "-02.html";
		}
		
		final int essence = MONSTER_ESSENCES.get(npc.getId());
		final String htmltext;
		
		if (hasQuestItems(player, essence)) {
			htmltext = npc.getId() + "-03.html";
		} else {
			giveItems(player, essence, 1);
			htmltext = npc.getId() + "-01.html";
			
			if (hasQuestItems(player, getRegisteredItemIds())) {
				qs.setCond(2, true);
			} else {
				playSound(player, Sound.ITEMSOUND_QUEST_ITEMGET);
			}
		}
		
		return htmltext;
	}
	
	@Override
	public String onTalk(L2Npc npc, L2PcInstance player) {
		final QuestState qs = getQuestState(player, true);
		String htmltext = getNoQuestMsg(player);
		if (Util.contains(SEPARATED_SOUL, npc.getId())) {
			switch (qs.getState()) {
				case State.COMPLETED:
					if (!qs.isNowAvailable()) {
						htmltext = "32864-02.html";
						break;
					}
					qs.setState(State.CREATED);
					// intentional fall-through
				case State.CREATED:
					htmltext = ((player.getLevel() >= MIN_LEVEL) ? "32864-01.htm" : "32864-03.html");
					break;
				case State.STARTED:
					switch (qs.getCond()) {
						case 1: {
							htmltext = (hasAtLeastOneQuestItem(player, getRegisteredItemIds()) ? "32864-09.html" : "32864-08.html");
							break;
						}
						case 2: {
							if (hasQuestItems(player, getRegisteredItemIds())) {
								rewardPlayer(player, npc);
								qs.exitQuest(QuestType.DAILY, true);
								htmltext = "32864-10.html";
							}
							break;
						}
					}
					break;
			}
		}
		return htmltext;
	}
	
	@Override
	public String onEvent(String event, L2Npc npc, L2PcInstance player) {
		final QuestState qs = player != null ? getQuestState(player, false) : null;
		String htmltext = null;
		switch (event) {
			case "32864-04.htm":
			case "32864-05.htm":
			case "32864-06.htm": {
				if ((qs != null) && qs.isCreated()) {
					htmltext = event;
				}
				break;
			}
			case "32864-07.htm": {
				if ((qs != null) && qs.isCreated()) {
					qs.startQuest();
					htmltext = event;
				}
				break;
			}
			case TIMER_UNSPAWN_RAID_CORPSE: {
				allowedPlayerMap.remove(npc.getObjectId());
				npc.deleteMe();
				break;
			}
		}
		
		return htmltext;
	}
	
	@Override
	public void onKill(L2Npc npc, L2PcInstance killer, boolean isSummon) {
		if (!killer.isInParty() || !killer.getParty().isInCommandChannel()) {
			// only the killing cc gets the quest
			return;
		}
		
		final L2CommandChannel cc = killer.getParty().getCommandChannel();
		if (cc.getMemberCount() < MIN_PLAYERS) {
			return;
		}
		
		Set<Integer> allowedPlayers = new HashSet<>();
		
		for (AggroInfo aggro : ((L2Attackable) npc).getAggroList().values()) {
			if ((aggro.getAttacker() == null) || !aggro.getAttacker().isPlayer()) {
				continue;
			}
			
			L2PcInstance attacker = aggro.getAttacker().getActingPlayer();
			
			if (attacker.isInParty() //
				&& attacker.getParty().isInCommandChannel() //
				&& attacker.getParty().getCommandChannel().equals(cc) // only players from the same cc are allowed
				&& Util.checkIfInRange(1500, npc, attacker, true)) {
				allowedPlayers.add(attacker.getObjectId());
			}
		}
		
		if (!allowedPlayers.isEmpty()) {
			// This depends on the boss respawn delay being at least 5 minutes.
			final L2Npc spawned = addSpawn(MONSTER_NPCS.get(npc.getId()), npc, true, 0);
			allowedPlayerMap.put(spawned.getObjectId(), allowedPlayers);
			startQuestTimer(TIMER_UNSPAWN_RAID_CORPSE, 300000, npc, null);
		}
	}
	
	private static void rewardPlayer(L2PcInstance player, L2Npc npc) {
		int chance = getRandom(10000);
		final int reward;
		int count = 1;
		
		if (chance < 170) {
			reward = ARMOR[getRandom(ARMOR.length)];
		} else if (chance < 200) {
			reward = ACCESSORIES[getRandom(ACCESSORIES.length)];
		} else if (chance < 270) {
			reward = WEAPONS[getRandom(WEAPONS.length)];
		} else if (chance < 325) {
			reward = BLESSED_SCROLL_ENCHANT_WEAPON_S;
		} else if (chance < 425) {
			reward = BLESSED_SCROLL_ENCHANT_ARMOR_S;
		} else if (chance < 925) {
			reward = ATTRIBUTE_CRYSTALS[getRandom(ATTRIBUTE_CRYSTALS.length)];
		} else if (chance < 1100) {
			reward = SCROLL_ENCHANT_WEAPON_S;
		} else {
			reward = GEMSTONE_S;
			count = 3;
		}
		
		giveItems(player, reward, count);
		L2Item item = ItemTable.getInstance().getTemplate(reward);
		NpcSay packet = new NpcSay(npc.getObjectId(), Say2.NPC_ALL, npc.getId(), NpcStringId.S1_RECEIVED_A_S2_ITEM_AS_A_REWARD_FROM_THE_SEPARATED_SOUL);
		packet.addStringParameter(player.getName());
		packet.addStringParameter(item.getName());
		npc.broadcastPacket(packet);
	}
}
