package com.rs.game.player;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import com.rs.cache.loaders.ClientScriptMap;
import com.rs.cache.loaders.GeneralRequirementMap;
import com.rs.cache.loaders.NPCDefinitions;
import com.rs.game.TemporaryAtributtes.Key;
import com.rs.game.player.actions.HomeTeleport;

public class TimersManager implements Serializable {


	private static final long serialVersionUID = -3278352340946510939L;
	
	private static final int BEAST_MENU_VAR = 4517;
	
	
	public static enum RecordKey {
		
		ARAXXI(0, false, true, 29),
		THE_BARROWS_BROTHERS(1, false, false, 29),
		THE_BARROWS_RISE_OF_THE_SIX(2, false, true, 29),
		CHAOS_ELEMENTAL(3, false, false, 35),
		COMMANDER_ZILYANA(4, true, true, 18),
		CORPOREAL_BEAST(5, false, false, 35),
		DAGANNOTH_KINGS(6, false, false, 31),
		GENERAL_GRAARDOR(7, true, true, 18),
		GIANT_MOLE(8, true, true, 22),
		FIGHT_KILN(9, true, false, 32), //har-aken
		KALPHITE_KING(10, true, false, 4), 
		KALPHITE_QUEEN(11, false, false, 4),
		KING_BLACK_DRAGON(12, false, false, 35),
		KREE_ARRA(13, true, true, 18),
		KRIL_TSUTSAROTH(14, true, true, 18),
		LEGIONES(15, true, false, 33),
		NEX(16, true, false, 18),
		QUEEN_BLACK_DRAGON(17, true, false, 24),
		FIGHT_CAVES(18, true, false, 32), //tztok-jad
		VORAGO(19, true, true, 22);
		
		private boolean hasHM, hasFastestKill;
		private int index, lodestoneComponent;
		
		
		private RecordKey(int index, boolean hasHM, boolean hasFastestKill, int lodestoneComponent) {
			this.index = index;
			this.hasHM = hasHM;
			this.hasFastestKill = hasFastestKill;
			this.lodestoneComponent = lodestoneComponent;
		}
	}
	
	private Player player;
	
	private Map<RecordKey, BossRecord> record;
	private int currentTime;
	
	private static class BossRecord implements Serializable {

		private static final long serialVersionUID = -8783909294743985403L;
		
		private int totalKills;
		private int totalHmKills;
		private int fastestKill;
		
	/*	private BossRecord(int totalKills, int totalHmKills, int fastestKill) {
			this.totalKills = totalKills;
			this.totalHmKills = totalHmKills;
			this.fastestKill = fastestKill;
		}*/
	}
	
	public TimersManager() {
		record = new HashMap<RecordKey, BossRecord>();
		currentTime = -1;
	}
	
	public void setPlayer(Player player) {
		this.player = player;
		if(record == null) //temporary
			record = new HashMap<RecordKey, BossRecord>();
	}
	
	public void init() {
		sendBossKills();
		sendSlayerCreatureKills();
	}
	
	public boolean isActive() {
		return currentTime >= 0;
	}
	
	
	public void process() {
		if(isActive() && currentTime < (Integer.MAX_VALUE / 30)) 
			currentTime++;
	}
	
	/*
	 * when boss respawns / instance starts depending in type
	 */
	public void sendTimer() {
		if (!isActive()) //starts it if wasnt on
			currentTime = 0;
		sendInterfaces();
	}
	
	
	public void sendInterfaces() {
		if (isActive())
			player.getInterfaceManager().sendTimerInterface();
	}
	
	/*
	 * doesnt save
	 */
	public void removeTimer() {
		removeTimer(null);
	}
	
	
	public void removeTimer(RecordKey key, boolean hm) {
		if (!isActive())  //shouldnt be used with this if not a timer boss
			return;
		if(key != null) {
			BossRecord record = getRecord(key);
			if(record == null) {
				record = new BossRecord();
				this.record.put(key, record);
			}
			record.fastestKill = record.fastestKill == 0 || record.fastestKill > currentTime ? currentTime : record.fastestKill;
			if(key.hasHM && hm)
				record.totalHmKills++;
			else
				record.totalKills++;
			sendBossKills();
		}
		currentTime = -1;
		player.getInterfaceManager().removeTimerInterface();
	}
	/*
	 * if null, doesnt save the time it done, if not null, saves
	 */
	public void removeTimer(RecordKey key) {
		removeTimer(key, false);
	}
	
	public void increaseKills(RecordKey key, boolean hm) {
		if (isActive() || key.hasFastestKill)  //shouldnt be used with this if a timer boss
			return;
		BossRecord record = getRecord(key);
		if(record == null) {
			record = new BossRecord();
			this.record.put(key, record);
		}
		if(key.hasHM && hm)
			record.totalHmKills++;
		else
			record.totalKills++;
		sendBossKills();
	}
	
	public BossRecord getRecord(RecordKey key) {
		return record.get(key);
	}

	
	public void setBeastMenu(int index) {
		if(index >= 3 || index < 0)
			return;
		player.getVarsManager().sendVar(BEAST_MENU_VAR, index);
		if(index == 0)
			openBossInfo(0);
	}
	
	//must be sent before
	public void sendBossKills() {
		BossRecord moleRecord = getRecord(RecordKey.GIANT_MOLE);
		player.getVarsManager().sendVarBit(22946, moleRecord != null ? moleRecord.totalKills : 0);
		player.getVarsManager().sendVarBit(22947, moleRecord != null ? moleRecord.totalHmKills : 0);
		BossRecord kbdRecord = getRecord(RecordKey.KING_BLACK_DRAGON);
		player.getVarsManager().sendVarBit(22948, kbdRecord != null ? kbdRecord.totalKills : 0);
		BossRecord barrowsRecord = getRecord(RecordKey.THE_BARROWS_BROTHERS);
		player.getVarsManager().sendVarBit(22949, barrowsRecord != null ? barrowsRecord.totalKills : 0);
		BossRecord chaosElementalRecord = getRecord(RecordKey.CHAOS_ELEMENTAL);
		player.getVarsManager().sendVarBit(22950, chaosElementalRecord !=  null ? chaosElementalRecord.totalKills : 0);
		BossRecord kalphiteQueenRecord = getRecord(RecordKey.KALPHITE_QUEEN);
		player.getVarsManager().sendVarBit(22951, kalphiteQueenRecord != null ? kalphiteQueenRecord.totalKills : 0);
		BossRecord fightCavesRecord = getRecord(RecordKey.FIGHT_CAVES);
		player.getVarsManager().sendVarBit(22952, fightCavesRecord != null ? fightCavesRecord.totalKills : 0);
		BossRecord corperealBeastRecord = getRecord(RecordKey.CORPOREAL_BEAST);
		player.getVarsManager().sendVarBit(22953, corperealBeastRecord != null ? corperealBeastRecord.totalKills : 0);
		BossRecord draganothKingsRecord = getRecord(RecordKey.DAGANNOTH_KINGS);
		player.getVarsManager().sendVarBit(22954, draganothKingsRecord != null ? draganothKingsRecord.totalKills : 0);
		BossRecord qbdRecord = getRecord(RecordKey.QUEEN_BLACK_DRAGON);
		player.getVarsManager().sendVarBit(22955, qbdRecord != null ? qbdRecord.totalKills : 0);
		BossRecord czRecord = getRecord(RecordKey.COMMANDER_ZILYANA);
		player.getVarsManager().sendVarBit(22956, czRecord != null ? czRecord.totalKills : 0);
		player.getVarsManager().sendVarBit(22957, czRecord != null ? czRecord.totalHmKills : 0);
		BossRecord generalGraadorRecord = getRecord(RecordKey.GENERAL_GRAARDOR);
		player.getVarsManager().sendVarBit(22958, generalGraadorRecord != null ? generalGraadorRecord.totalKills : 0);
		player.getVarsManager().sendVarBit(22959, generalGraadorRecord != null ? generalGraadorRecord.totalHmKills : 0);
		BossRecord kreeAraRecord = getRecord(RecordKey.KREE_ARRA);
		player.getVarsManager().sendVarBit(22960, kreeAraRecord != null ? kreeAraRecord.totalKills : 0);
		player.getVarsManager().sendVarBit(22961, kreeAraRecord != null ? kreeAraRecord.totalHmKills : 0);
		BossRecord krilTsutsarothRecord = getRecord(RecordKey.KRIL_TSUTSAROTH);
		player.getVarsManager().sendVarBit(22962, krilTsutsarothRecord != null ? krilTsutsarothRecord.totalKills : 0);
		player.getVarsManager().sendVarBit(22963,krilTsutsarothRecord != null ? krilTsutsarothRecord.totalHmKills : 0);
		BossRecord kilnRecord = getRecord(RecordKey.FIGHT_KILN);
		player.getVarsManager().sendVarBit(22964, kilnRecord != null ? kilnRecord.totalKills : 0);
		BossRecord kalphiteKingRecord = getRecord(RecordKey.KALPHITE_KING);
		player.getVarsManager().sendVarBit(22965, kalphiteKingRecord != null ? kalphiteKingRecord.totalKills : 0);
		BossRecord legionesRecord = getRecord(RecordKey.LEGIONES);
		player.getVarsManager().sendVarBit(22966, legionesRecord != null ? legionesRecord.totalKills : 0);
		BossRecord nexRecord = getRecord(RecordKey.NEX);
		player.getVarsManager().sendVarBit(22967, nexRecord != null ? nexRecord.totalKills : 0);
		BossRecord riseOfTheSixRecord = getRecord(RecordKey.THE_BARROWS_RISE_OF_THE_SIX);
		player.getVarsManager().sendVarBit(22968, riseOfTheSixRecord != null ? riseOfTheSixRecord.totalKills : 0);
		BossRecord araxxiRecord = getRecord(RecordKey.ARAXXI);
		player.getVarsManager().sendVarBit(22969, araxxiRecord != null ? araxxiRecord.totalKills : 0);
		BossRecord voragoRecord = getRecord(RecordKey.VORAGO);
		player.getVarsManager().sendVarBit(22970, voragoRecord != null ? voragoRecord.totalKills : 0);
		player.getVarsManager().sendVarBit(22971, voragoRecord != null ? voragoRecord.totalHmKills : 0);
		
	}
	
	//TODO tracking at slayer itself
	public void sendSlayerCreatureKills() {
		player.getVarsManager().sendVarBit(22921, 0);//Terror Dogs
		player.getVarsManager().sendVarBit(22922, 0);//Bloodvields
		player.getVarsManager().sendVarBit(22923, 0);//Warped Tort
		player.getVarsManager().sendVarBit(22924, 0);//Abberant Specters
		player.getVarsManager().sendVarBit(22925, 0);//Dust Devils
		player.getVarsManager().sendVarBit(22926, 0);//Automations
		player.getVarsManager().sendVarBit(22927, 0);//Skeletal Wyverns
		player.getVarsManager().sendVarBit(22928, 0);//Jungle StykeWyrms
		player.getVarsManager().sendVarBit(22929, 0);//Aquanites
		player.getVarsManager().sendVarBit(22930, 0);//Nechraels
		player.getVarsManager().sendVarBit(22931, 0);//Mutated Jadinkos
		player.getVarsManager().sendVarBit(22932, 0);//Ascension Creatures
		player.getVarsManager().sendVarBit(22933, 0);//Polypore Creatures
		player.getVarsManager().sendVarBit(22934, 0);//Spiritual Mages
		player.getVarsManager().sendVarBit(22935, 0);//Abyssal Demons
		player.getVarsManager().sendVarBit(22936, 0);//Dark beasts
		player.getVarsManager().sendVarBit(22937, 0);//Airut
		player.getVarsManager().sendVarBit(22938, 0);//Ice StykeWyrms
		player.getVarsManager().sendVarBit(22939, 0);//Kal'gerion demons
		player.getVarsManager().sendVarBit(22940, 0);//Glaciors
		player.getVarsManager().sendVarBit(22941, 0);//Tormented Demons
		player.getVarsManager().sendVarBit(22942, 0);//Gargoyls
		player.getVarsManager().sendVarBit(22943, 0);//Muspha
		player.getVarsManager().sendVarBit(22944, 0);//Nihil
		player.getVarsManager().sendVarBit(22945, 0);//Desert StykeWyrms
	}
	
	public void teleportToLodestone() {
		if(player.getVarsManager().getValue(BEAST_MENU_VAR) != 0)
			return;
		RecordKey key = (RecordKey) player.getTemporaryAttributtes().remove(Key.BOSS_INFO);
		if(key == null)
			return;
		player.getInterfaceManager().closeMenu();
		player.stopAll();
		HomeTeleport.useLodestone(player, key.lodestoneComponent);
	}
	
	public void openBossInfo(int index) {
		if(index >= RecordKey.values().length || index < 0 || player.getVarsManager().getValue(BEAST_MENU_VAR) != 0)
			return;
		
		RecordKey key = RecordKey.values()[index];
		
		player.getTemporaryAttributtes().put(Key.BOSS_INFO, key);
		
		BossRecord record = getRecord(key);
		
		player.getPackets().sendCSVarInteger(4486, record == null ? 0 : record.totalKills);
		player.getPackets().sendCSVarInteger(4487, !key.hasHM ? -1 : record == null ? 0 : record.totalKills);
		player.getPackets().sendCSVarInteger(4488, !key.hasFastestKill ? -1 : record == null ? 0 : record.fastestKill*30);

		
		GeneralRequirementMap data = GeneralRequirementMap.getMap(ClientScriptMap.getMap(9031).getIntValue(index));
		player.getPackets().sendCSVarInteger(4484, NPCDefinitions.getNPCDefinitions(data.getIntValue(1347)).renderEmote);
		player.getPackets().sendCSVarInteger(4485, data.getId()); 
	}
	
	
	//ignore this. not related to code. only use removetimer and sendtimer methods
	public void showTimer() {
		if (!isActive()) //shouldnt happen unless u open inter manualy
			return;

		player.getPackets().sendExecuteScript(720);
		player.getPackets().sendCSVarInteger(4258, currentTime * 30);
	}
	
	
}
