package com.rs.game.minigames.pest;

import com.rs.game.TemporaryAtributtes.Key;
import com.rs.game.item.Item;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.player.actions.HerbCleaning.Herbs;
import com.rs.game.player.content.Nest;
import com.rs.utils.Utils;

public class CommendationExchange {

    private static final int PURCHASE_INTERFACE = 1011, EXP_TYPE = 1, VOID_TYPE = 2, CONSUMABLE_TYPE = 3;
    
   enum CommendationStock {
       
       ATTACK_XP(1, Skills.ATTACK | EXP_TYPE << 24, new int[] {66, 84, 86}),
       STRENGTH_XP(1, Skills.STRENGTH | EXP_TYPE << 24, new int[] {98, 100, 102}),
       DEFENCE_XP(1, Skills.DEFENCE | EXP_TYPE << 24, new int[] {114, 116, 118}),
       CONSTITUTION_XP(1, Skills.HITPOINTS | EXP_TYPE << 24, new int[] {130, 132, 134}),
       RANGE_XP(1, Skills.RANGE | EXP_TYPE << 24, new int[] {146, 148, 150}),
       MAGE_XP(1, Skills.MAGIC | EXP_TYPE << 24, new int[] {164, 166, 168}),
       PRAYER_XP(1, Skills.PRAYER | EXP_TYPE << 24, new int[] {179, 181, 183}),
       SUMMONING_XP(1, Skills.SUMMONING | EXP_TYPE << 24, new int[] {338, 340, 342}),
       
       VOID_KNIGHT_MELEE_HELM(200, 11676 | VOID_TYPE << 24, new int [] {362}),
       VOID_KNIGHT_RANGER_HELM(200, 11675 | VOID_TYPE << 24, new int [] {374}),
       VOID_KNIGHT_MAGE_HELM(200, 11674 | VOID_TYPE << 24, new int [] {386}),
       VOID_KNIGHT_TOP(250, 8839 | VOID_TYPE << 24, new int [] {398}),
       VOID_KNIGHT_ROBES(250, 8840 | VOID_TYPE << 24, new int [] {410}),
       VOID_KNIGHT_GLOVES(150, 8842 | VOID_TYPE << 24, new int [] {422}),
       
       VOID_KNIGHT_MACE(250, 8841 | VOID_TYPE << 24, new int [] {195}),
       VOID_KNIGHT_DEFLECTOR(150, 19711 | VOID_TYPE << 24, new int [] {209}),
       VOID_KNIGHT_SEAL(10, 11666 | VOID_TYPE << 24, new int [] {220}),
       JESSIKA_SWORD(350, 31639 | VOID_TYPE << 24, new int [] {433}),
       
       HERBLORE_PACK(30, 0 | CONSUMABLE_TYPE << 24, new int[] {231}),
       MINERAL_PACK(15, 0 | CONSUMABLE_TYPE << 24, new int[] {242}),
       SEED_PACK(15, 0 | CONSUMABLE_TYPE << 24, new int[] {253}),
       ARMOUR_PATCH(444, 31640 | CONSUMABLE_TYPE << 24, new int[] {444}),
       
       SPINNER_CHARMS(2, 27062 | CONSUMABLE_TYPE << 24, new int[] {264, 266, 268}),
       TORCHER_CHARMS(2, 27063 | CONSUMABLE_TYPE << 24, new int[] {279, 281, 283}),
       RAVAGER_CHARMS(2, 27060 | CONSUMABLE_TYPE << 24, new int[] {294, 296, 298}),
       SHIFTER_CHARMS(2, 27061 | CONSUMABLE_TYPE << 24, new int[] {309, 311, 313}),
       ;
       
	private CommendationStock(int cost, int typeHash, int[] components) {
	    this.cost = cost;
	    this.typeHash = typeHash;
	    this.components = components;
	}

	private int[] components;
	private int cost, typeHash;

	public int[] getComponents() {
	    return components;
	}

	public int getCost() {
	    return cost;
	}

	public int getTypeHash() {
	    return typeHash;
	}

	public String getName() {
	    return Utils.formatPlayerNameForDisplay(name());
	}
    }

    public static void openExchangeShop(Player player) {
	player.getInterfaceManager().sendCentralInterface(PURCHASE_INTERFACE);
	player.getTemporaryAttributtes().put(Key.PEST_REWARD_TAB, 0);
	player.getVarsManager().sendVar(1660, 1250);// Conquest Ranking
	refreshCommendations(player);
    }

    private static void selectPurchase(Player player, CommendationStock stock, int index) {
	int key = stock.getTypeHash() & 0xFFFF;
	int type = stock.getTypeHash() >> 24;

	if (type == EXP_TYPE) {
	    if (player.getSkills().getLevelForXp(key) < 25) {
		player.getPackets().sendGameMessage(
			"A " + Skills.SKILL_NAME[key] + " level of at least 25 is required to purchase experience.");
		return;
	    }
	} else if (type == VOID_TYPE) {
	    if (stock != CommendationStock.VOID_KNIGHT_SEAL) {
		if (!player.getSkills().hasRequiriments(Skills.ATTACK, 42, Skills.STRENGTH, 42, Skills.DEFENCE, 42,
			Skills.HITPOINTS, 42, Skills.RANGE, 42, Skills.MAGIC, 42, Skills.PRAYER, 22)) {
		    player.getPackets()
			    .sendGameMessage("Higher levels are required in order to purchase Void Equipment.");
		    return;
		}
	    }
	} else if (type == CONSUMABLE_TYPE) {
	    if (stock == CommendationStock.HERBLORE_PACK) {
		if (player.getSkills().getLevelForXp(Skills.HERBLORE) < 25) {
		    player.getPackets().sendGameMessage(
			    "A Herblore level of 25 is required in order to purchase a herblore pack.");
		    return;
		}
	    } else if (stock == CommendationStock.MINERAL_PACK) {
		if (player.getSkills().getLevelForXp(Skills.MINING) < 25) {
		    player.getPackets()
			    .sendGameMessage("A Mining level of 25 is required in order to purchase a mineral pack.");
		    return;
		}
	    } else if (stock == CommendationStock.SEED_PACK) {
		if (player.getSkills().getLevelForXp(Skills.FARMING) < 25) {
		    player.getPackets()
			    .sendGameMessage("A Farming level of 25 is required in order to purchase a seed pack.");
		    return;
		}
	    }
	}
	int rate = (int) Math.pow(10, index);
	if (type == CONSUMABLE_TYPE && stock.getComponents().length > 1) //Charms exception required.
	    rate = player.getCommendation() / 2;
	int cost = stock.getCost() * rate;
	if (player.getCommendation() < cost) {
	    player.getPackets()
		    .sendGameMessage(cost + " Commendations are required in order to complete this purchase.");
	    return;
	}
	player.getTemporaryAttributtes().put(Key.PEST_REWARD_RATE, rate);
	player.getTemporaryAttributtes().put(Key.PEST_REWARD_STOCK, stock);

	player.getPackets().sendHideIComponent(PURCHASE_INTERFACE, 4, false);
	player.getPackets().sendIComponentText(PURCHASE_INTERFACE, 320,
		"Are you sure you wish to exchange " + cost + " Commendations in return for "
			+ (stock.getComponents().length > 1 ? "" : "a ") + "" + stock.getName() + "?");
    }

    private static void confirmPurchase(Player player, boolean complete) {
	if (complete)
	    completePurchase(player);
	player.getTemporaryAttributtes().remove(Key.PEST_REWARD_STOCK);
	player.getTemporaryAttributtes().remove(Key.PEST_REWARD_RATE);
	player.getPackets().sendHideIComponent(PURCHASE_INTERFACE, 4, true);
    }

    private static void completePurchase(Player player) {
	CommendationStock stock = (CommendationStock) player.getTemporaryAttributtes().get(Key.PEST_REWARD_STOCK);
	int rate = (int) player.getTemporaryAttributtes().get(Key.PEST_REWARD_RATE);

	int key = stock.getTypeHash() & 0xFFFF;
	int type = stock.getTypeHash() >> 24;
	if (type == EXP_TYPE) {
	    double experience = getExperience(player, key, rate);
	    player.getSkills().addXp(key, experience);
	    player.getPackets().sendGameMessage("You exchange " + rate + " Commendations and recieve "
		    + (int) experience + " " + stock.getName() + " in return.");
	} else if (type == VOID_TYPE || type == CONSUMABLE_TYPE) {
	    boolean spaceAvailable = player.getInventory().hasFreeSlots();
	    Item[] packs = new Item[stock == CommendationStock.SEED_PACK ? 3 : 2];
	    if (key == 0) {
		if (stock == CommendationStock.HERBLORE_PACK) {
		    packs[0] = new Item(Herbs.values()[Utils.random(5)].getHerbId() + 1, Utils.random(1, 4));
		    packs[1] = new Item(Herbs.values()[Utils.random(Herbs.values().length - 1)].getHerbId() + 1,
			    Utils.random(1, 3));
		} else if (stock == CommendationStock.MINERAL_PACK) {
		    packs[0] = new Item(441, Utils.random(1, 30));
		    packs[1] = new Item(454, Utils.random(1, 20));
		} else if (stock == CommendationStock.SEED_PACK) {
		    packs[0] = new Item(Nest.SEEDS[0][Utils.random(Nest.SEEDS[0].length)], Utils.random(1, 5));
		    packs[1] = new Item(Nest.SEEDS[0][Utils.random(Nest.SEEDS[0].length)], Utils.random(1, 3));
		    packs[2] = new Item(Nest.SEEDS[1][Utils.random(Nest.SEEDS[1].length)], Utils.random(1, 2));
		}
		spaceAvailable = player.getInventory().getFreeSlots(packs) - packs.length >= 0;
		if (!spaceAvailable)
		    spaceAvailable = player.getInventory().containsItems(packs);
	    }
	    if (!spaceAvailable) {
		player.getPackets().sendGameMessage("Not enough space in your inventory.");
		return;
	    }
	    if (key != 0)
		player.getInventory().addItem(key, rate);
	    else {
		for (Item pack : packs)
		    player.getInventory().addItem(pack);
	    }
	}
	player.setCommendation(player.getCommendation() - (stock.getCost() * rate));
	refreshCommendations(player);
    }

    public static void handleButtonOptions(Player player, int componentId) {
	if (componentId == 344 || componentId == 6 || componentId == 68)
	    switchTab(player, 0, (int) player.getTemporaryAttributtes().get(Key.PEST_REWARD_TAB));
	else if (componentId == 8 || componentId == 24 || componentId == 70)
	    switchTab(player, 1, (int) player.getTemporaryAttributtes().get(Key.PEST_REWARD_TAB));
	else if (componentId == 26 || componentId == 72 || componentId == 348)
	    switchTab(player, 2, (int) player.getTemporaryAttributtes().get(Key.PEST_REWARD_TAB));
	else if (componentId == 12 || componentId == 28 || componentId == 350)
	    switchTab(player, 3, (int) player.getTemporaryAttributtes().get(Key.PEST_REWARD_TAB));
	else if (componentId == 323 || componentId == 325)
	    confirmPurchase(player, componentId == 323);
	else {
	    for (CommendationStock stock : CommendationStock.values())
		for (int count = 0; count < stock.getComponents().length; count++)
		    if (componentId == stock.getComponents()[count])
			selectPurchase(player, stock, count);
	}
    }

    private static void refreshCommendations(Player player) {
	player.getVarsManager().sendVarBit(4861, player.getCommendation());
    }

    private static void switchTab(Player player, int tab, int previousTab) {
	player.getPackets().sendHideIComponent(PURCHASE_INTERFACE, tab, false);
	player.getPackets().sendHideIComponent(PURCHASE_INTERFACE, previousTab, true);
	player.getTemporaryAttributtes().put(Key.PEST_REWARD_TAB, tab);
    }

    private static double getExperience(Player player, int skill, int rate) {
	int level = player.getSkills().getLevelForXp(skill);
	double experience = Math.pow(level, 2) / ((skill == Skills.MAGIC || skill == Skills.RANGE) ? 5.195
		: (skill == Skills.PRAYER || skill == Skills.SUMMONING) ? 19.23 : 5.0);
	double bonus = experience * (Math.floor(0.1D * rate) * 0.1D);
	return experience * rate + bonus;
    }
}
