package net.piratjsk.sddls.listeners;

import net.piratjsk.sddls.mount.ProtectedMount;
import net.piratjsk.sddls.signature.Signature;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.configuration.Configuration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;

import net.piratjsk.sddls.Sddls;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.projectiles.ProjectileSource;

import java.util.UUID;
import java.util.stream.Collectors;

import static net.piratjsk.sddls.utils.StringUtils.capitalizeFirstLetter;

public final class MountListener implements Listener {

    @EventHandler
    public void onMountAccess(final PlayerInteractEntityEvent event) {
        if (!Sddls.canBeProtected(event.getRightClicked().getType())) return;
        final ProtectedMount mount = ProtectedMount.fromEntity(event.getRightClicked());
        if (mount.isProtectedFromPlayer(event.getPlayer())) {
            event.setCancelled(true);
            sendNoAccessMessage(event.getPlayer(), mount);
        }
    }

    @EventHandler
    public void onMountDamage(final EntityDamageEvent event) {
        if (!Sddls.canBeProtected(event.getEntityType())) return;
        final ProtectedMount mount = ProtectedMount.fromEntity(event.getEntity());
        final DamageDealer damageDealer = getDamageDealer(event);
        if (shouldBeProtected(mount, damageDealer))
            event.setCancelled(true);
    }

    private boolean shouldBeProtected(final ProtectedMount mount, final DamageDealer damageDealer) {
        if (damageDealer.isPlayer()) {
            final Player player = getPlayer(damageDealer);
            return mount.isProtectedFromPlayer(player);
        }
        return mount.isProtectedFromEnvironment();
    }

    private Player getPlayer(final DamageDealer damageDealer) {
        return Bukkit.getPlayer(damageDealer.uuid);
    }

    private void sendNoAccessMessage(final Player player, final ProtectedMount mount) {
        final Configuration config = JavaPlugin.getPlugin(Sddls.class).getConfig();
        final Entity entity = mount.getEntity();
        final String type = entity.getType().toString().toLowerCase().replaceAll("_", "-");
        final String name = entity.getCustomName() != null ? entity.getCustomName() : type;
        final String players = mount.getSaddle().getSignatures().stream()
                .map(Signature::getName)
                .collect(Collectors.joining(", "));
        final String defaultMessage = config.getString("no-access-msg", "&6[Sddls] &7You don't have access to this %mount%.");
        final String message = config.getString("no-access-msg-" + type, defaultMessage)
                .replaceAll("%mount%", type)
                .replaceAll("%Mount%", capitalizeFirstLetter(type))
                .replaceAll("%name%", name)
                .replaceAll("%Name%", capitalizeFirstLetter(name))
                .replaceAll("%players%", players);
        player.sendMessage(ChatColor.translateAlternateColorCodes('&', message));
    }

    private DamageDealer getDamageDealer(final EntityDamageEvent event) {
        if (!(event instanceof EntityDamageByEntityEvent)) return new DamageDealer();
        final EntityDamageByEntityEvent damageEvent = (EntityDamageByEntityEvent) event;
        final Entity damager = damageEvent.getDamager();
        if (damager instanceof Projectile) {
            final ProjectileSource shooter = ((Projectile) damager).getShooter();
            if (shooter instanceof Entity)
                return new DamageDealer((Entity) shooter);
        }
        return new DamageDealer(damageEvent.getDamager());
    }

    private final class DamageDealer {
        private final EntityType type;
        private final UUID uuid;
        DamageDealer() {
            this.type = null;
            this.uuid = null;
        }
        DamageDealer(final Entity entity) {
            this.type = entity.getType();
            this.uuid = entity.getUniqueId();
        }
        boolean isPlayer() {
            return type == EntityType.PLAYER;
        }
    }

}

@@ -1601,37 +1601,32 @@
 final Damage
-Deale
 r damage
 Dealer = get
@@ -1613,21 +1613,16 @@
 r damage
-Deale
 r = getD
@@ -1626,21 +1626,16 @@
 etDamage
-Deale
 r(event)
@@ -1679,21 +1679,16 @@
 , damage
-Deale
 r))%0A    
@@ -1802,37 +1802,32 @@
 final Damage
-Deale
 r damage
 Dealer) %7B%0A  
@@ -1806,37 +1806,32 @@
 l Damager damage
-Deale
 r) %7B%0A        if 
@@ -1837,21 +1837,16 @@
  (damage
-Deale
 r.isPlay
@@ -1903,21 +1903,16 @@
 r(damage
-Deale
 r);%0A    
@@ -2076,21 +2076,16 @@
 mage
-Deale
 r damage
 Deal
@@ -2080,21 +2080,16 @@
 r damage
-Deale
 r) %7B%0A   
@@ -2123,21 +2123,16 @@
 r(damage
-Deale
 r.uuid);
@@ -2268,40 +2268,26 @@
 g = 
-JavaPlugin.getPlugin(Sddls.class
+Sddls.getInstance(
 ).ge
@@ -3295,21 +3295,16 @@
 e Damage
-Deale
 r getDam
@@ -3302,29 +3302,24 @@
 er getDamage
-Deale
 r(final Enti
@@ -3417,21 +3417,16 @@
 w Damage
-Deale
 r();%0A   
@@ -3699,55 +3699,8 @@
 ();%0A
-            if (shooter instanceof Entity)%0A    
     
@@ -3724,21 +3724,16 @@
 w Damage
-Deale
 r((Entit
@@ -3780,21 +3780,16 @@
 w Damage
-Deale
 r(damage
@@ -3846,21 +3846,16 @@
 s Damage
-Deale
 r %7B%0A    
@@ -3936,21 +3936,16 @@
   Damage
-Deale
 r() %7B%0A  
@@ -4030,13 +4030,8 @@
 mage
-Deale
 r(fi

rename DamageDealer back to Damager