package de.tobiyas.racesandclasses.hotkeys;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import de.tobiyas.racesandclasses.RacesAndClasses;
import de.tobiyas.racesandclasses.APIs.CooldownApi;
import de.tobiyas.racesandclasses.configuration.global.GeneralConfig;
import de.tobiyas.racesandclasses.playermanagement.player.RaCPlayer;
import de.tobiyas.racesandclasses.saving.PlayerSavingData;
import de.tobiyas.racesandclasses.traitcontainer.interfaces.markerinterfaces.Trait;
import de.tobiyas.racesandclasses.traitcontainer.interfaces.markerinterfaces.TraitWithRestrictions;
import de.tobiyas.racesandclasses.util.consts.PermissionNode;
public class HotKeyInventory {
/**
* The Key at start to identify the Item.
*/
private static final String BIND_KEY = ChatColor.AQUA + "Trait: ";
/**
* The Hot-Key Bindings.
*/
private final Map<Integer,Trait> traitBindings = new HashMap<Integer, Trait>();
/**
* The Old Hotkey Bar.
*/
private final Map<Integer,ItemStack> oldHotkeyBar = new HashMap<Integer, ItemStack>();
/**
* The Player how is the Owner of the HotKeys.
*/
private final RaCPlayer player;
/**
* If the Player is in Skill Mode or not.
*/
private boolean isInSkillMode = false;
public HotKeyInventory(RaCPlayer player) {
this.player = player;
loadFromFile();
}
/**
* Loads the HotKeyInventory Bindings from the File.
*/
public void loadFromFile(){
traitBindings.clear();
PlayerSavingData data = player.getPlayerSaveData();
Map<Integer,String> bindings = data.getHotKeys();
//Read the Data.
for(Map.Entry<Integer,String> entry : bindings.entrySet()){
int key = entry.getKey();
String name = entry.getValue();
for(Trait trait : player.getTraits()){
if(trait.getDisplayName().equals(name)){
this.traitBindings.put(key, trait);
}
}
}
}
/**
* Binds a trait to the slot passed.
*
* @param slot to bind to
* @param trait to bind.
*/
public void bindTrait(int slot, Trait trait){
//first check if legit trait.
if(trait == null || !trait.isBindable()) return;
PlayerSavingData data = player.getPlayerSaveData();
data.setHotKey(slot, trait.getDisplayName());
this.traitBindings.put(slot, trait);
}
/**
* Removes any trait from the Slot.
*
* @param slot to clear
*/
public void clearSlot(int slot){
if(!traitBindings.containsKey(slot)) return;
PlayerSavingData data = player.getPlayerSaveData();
data.clearHotKey(slot);
this.traitBindings.remove(slot);
}
/**
* Clears all Trait slots.
*/
public void clearAllSlots(){
traitBindings.clear();
PlayerSavingData data = player.getPlayerSaveData();
data.clearHotKeys();
}
/**
* Call this regularly to update playerInventory View.
*/
public void updatePlayerInventory(){
if(!player.isOnline()) return;
if(!isInSkillMode) return; //nothing to update.
if(traitBindings.isEmpty()) return; //nothing to update.
Material shortcutMat = RacesAndClasses.getPlugin().getConfigManager().getGeneralConfig().getConfig_hotkeys_material();
short maxShortcutDurability = shortcutMat.getMaxDurability();
for(Entry<Integer,Trait> entry : traitBindings.entrySet()){
int slot = entry.getKey();
Trait trait = entry.getValue();
ItemStack item = player.getPlayer().getInventory().getItem(slot);
if(item == null || item.getType() != shortcutMat) continue;
if(trait instanceof TraitWithRestrictions){
TraitWithRestrictions res = (TraitWithRestrictions) trait;
int maxCD = res.getMaxUplinkTime();
if(maxCD > 0){
String cooldownName = ((TraitWithRestrictions) trait).getCooldownName();
int cd = CooldownApi.getCooldownOfPlayer(player.getName(), cooldownName);
if(cd >= 0){
float percent = (float)cd / (float)maxCD;
float val = maxShortcutDurability * percent;
if(val <= 0) val = 1; if(val >= maxShortcutDurability) val = maxShortcutDurability - 1;
item.setDurability((short) val);
}
if(cd < 0){
item.setDurability((short) 0);
}
}
}
}
}
/**
* Changes the Hotbar to the build Inv.
*/
public void changeToBuildInv(){
if(!isInSkillMode) return;
Player player = this.player.getPlayer();
if(player == null) return;
if(!player.isOnline()) return; //can't set offline players items!
Set<Integer> disabled = RacesAndClasses.getPlugin().getConfigManager().getGeneralConfig().getConfig_disabledHotkeySlots();
//first clear the old ones.
for(int i = 0; i < 9; i++) {
if(!disabled.contains(i) && traitBindings.containsKey(i)) player.getInventory().setItem(i, null);
}
//now refill with the old ones.
for(Entry<Integer,ItemStack> entry : oldHotkeyBar.entrySet()){
int slot = entry.getKey();
ItemStack item = entry.getValue();
if(disabled.contains(slot)) continue;
player.getInventory().setItem(slot, item);
}
oldHotkeyBar.clear();
isInSkillMode = false;
}
/**
* Change the Build-Menu to the Skill Menu.
*/
public void changeToSkillInv(){
if(isInSkillMode) return;
Player player = this.player.getPlayer();
if(player == null) return;
GeneralConfig config = RacesAndClasses.getPlugin().getConfigManager().getGeneralConfig();
Set<Integer> disabled = config.getConfig_disabledHotkeySlots();
//Add Permissions based:
if(config.isConfig_use_permissions_for_hotkeys()){
for(int i = 0; i < 9; i++){
if(!RacesAndClasses.getPlugin().getPermissionManager().checkPermissionsSilent(player, PermissionNode.hotkeyPre + i)){
disabled.add(i);
}
}
}
//remove in case...
oldHotkeyBar.clear();
//try to move the stuff away that is in the way!
for(int i = 0; i < 9; i++){
if(disabled.contains(i)) continue;
if(!traitBindings.containsKey(i)) continue;
ItemStack toMove = player.getInventory().getItem(i);
if(toMove == null || toMove.getType() == Material.AIR) continue;
//now we have to move the Item to a better slot!
for(int slot = 9; slot < player.getInventory().getSize(); slot++){
ItemStack toMoveTo = player.getInventory().getItem(slot);
if(toMoveTo == null || toMoveTo.getType() == Material.AIR){
//we found a good slot!
player.getInventory().setItem(slot, toMove.clone());
player.getInventory().setItem(i, null);
break;
}
}
}
//first save the old items
for(int i = 0; i < 9; i++){
if(disabled.contains(i)) continue;
if(!traitBindings.containsKey(i)) continue;
ItemStack item = player.getInventory().getItem(i);
if(item != null && item.getType() != Material.AIR) oldHotkeyBar.put(i, item.clone());
ItemStack newItem = generateItem(traitBindings.get(i));
player.getInventory().setItem(i, newItem == null ? getEmptyItem() : newItem);
}
isInSkillMode = true;
}
/**
* This forces reseting all Mats when in Skil mode.
*/
public void forceUpdateOfInv(){
if(!isInSkillMode) return;
Player player = this.player.getPlayer();
if(player == null) return;
Set<Integer> disabled = RacesAndClasses.getPlugin().getConfigManager().getGeneralConfig().getConfig_disabledHotkeySlots();
//now set the Items to the quickslot bar.
for(int i = 0; i < 9; i++){
if(disabled.contains(i)) continue;
if(!traitBindings.containsKey(i)) continue;
ItemStack item = generateItem(traitBindings.get(i));
player.getInventory().setItem(i, item == null ? getEmptyItem() : item);
}
}
/**
* Generates an Item to the Trait.
*
* @param trait to generate to
*
* @return the item or null if null is passed.
*/
public static ItemStack generateItem(Trait trait){
if(trait == null) return null;
Material shortcutMat = RacesAndClasses.getPlugin().getConfigManager().getGeneralConfig().getConfig_hotkeys_material();
ItemStack item = new ItemStack(shortcutMat);
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(BIND_KEY + trait.getDisplayName());
List<String> lore = new LinkedList<String>();
lore.add("Switch the item to this slot to cast the Spell,");
lore.add("or simply right-click with it.");
lore.add("");
lore.add(ChatColor.YELLOW + trait.getPrettyConfiguration());
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
return item;
}
/**
* Generates an Empty Slot itme.
*
* @return the item for an empty Slot.
*/
public static ItemStack getEmptyItem(){
ItemStack item = new ItemStack(Material.FLINT);
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(BIND_KEY + "EMPTY");
List<String> lore = new LinkedList<String>();
lore.add("Put an Skill to this Slot to to fill it.");
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
return item;
}
/**
* Returns true if in Building mode.
*
* @return true if in building mode.
*/
public boolean isInBuildingMode(){
return !isInSkillMode;
}
/**
* Returns true if in Skill mode.
*
* @return true if in Skill mode.
*/
public boolean isInSkillMode(){
return isInSkillMode;
}
/**
* Returns a copy of the Bindings.
*
* @return bindings.
*/
public Map<Integer,Trait> getBindings() {
return new HashMap<Integer,Trait>(this.traitBindings);
}
}