package me.km.blockprotections;

import me.km.overrides.ModEntityPlayerMP;
import me.km.permissions.PermissionManager;
import me.km.utils.Location;
import net.minecraft.block.Block;
import net.minecraft.block.ContainerBlock;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.tags.BlockTags;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent;

public class BlockProtectionEvents
{
    private final static String BLOCK_BYPASS = "block.bypass";
    
    private final IBlockProtection bank;
    private final PermissionManager perms;
    
    public BlockProtectionEvents(IBlockProtection bank, PermissionManager perms) 
    {
        this.bank = bank;
        this.perms = perms;
    }
    
    private BlockPos getSameNearbyBlock(IWorld w, BlockPos pos, Block b)
    {           
        Location l = new Location(w, pos);
        if(l.getRelativeBlockState(1, 0, 0).getBlock() == b)
        {
            return pos.add(1, 0, 0);
        }
        else if(l.getRelativeBlockState(-1, 0, 0).getBlock() == b)
        {
            return pos.add(-1, 0, 0);
        }
        else if(l.getRelativeBlockState(0, 0, 1).getBlock() == b)
        {
            return pos.add(0, 0, 1);
        }
        else if(l.getRelativeBlockState(0, 0, -1).getBlock() == b)
        {
            return pos.add(0, 0, -1);
        }
        return null;
    }
    
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public void onBlockPlace(BlockEvent.EntityPlaceEvent e)
    {
        Block b = e.getPlacedBlock().getBlock();
        if(!(e.getEntity() instanceof ModEntityPlayerMP))
        {
            return;
        }
        ModEntityPlayerMP p = (ModEntityPlayerMP) e.getEntity();
        IWorld w = e.getWorld();
        
        if(b == Blocks.CHEST || b == Blocks.TRAPPED_CHEST) // Deny placing chests near other protected chests
        {
            BlockPos otherChest = getSameNearbyBlock(w, e.getPos(), b);
            if(otherChest != null && !bank.hasAccess(otherChest, w, p) && !perms.hasPermission(p, BLOCK_BYPASS))
            {
                e.setCanceled(true);
            }        
        } 
        else if(b == Blocks.HOPPER) // Deny placing of hoppers under blocks
        {
            BlockPos pos = e.getPos().add(0, 1, 0);
            if(w.getBlockState(pos).getBlock() instanceof ContainerBlock)
            {
                if(!bank.hasAccess(pos, w, p) && !perms.hasPermission(p, BLOCK_BYPASS))
                {
                    e.setCanceled(true);
                }               
            }            
        }
    }
    
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public void onBlockBreak(BlockEvent.BreakEvent e)
    {
        ModEntityPlayerMP p = (ModEntityPlayerMP) e.getPlayer();
        BlockState state = e.getState();

        BlockPos pos = e.getPos();        
        if(BlockTags.DOORS.contains(state.getBlock()) && state.get(DoorBlock.HALF) == DoubleBlockHalf.UPPER)
        {
            pos = pos.add(0, -1, 0);
        } 
        IWorld w = e.getWorld();
        if(bank.hasAccess(pos, w, p) || perms.hasPermission(p, BLOCK_BYPASS))
        {
            // ToDo remove protection
            return;
        }   
        e.setCanceled(true);          
    }
    
    @SubscribeEvent(priority = EventPriority.HIGHEST)
    public void onContainerOpen(PlayerInteractEvent.RightClickBlock e)
    {
        if(e.getHand() != Hand.MAIN_HAND)
        {
            return;
        }
        BlockState state = e.getWorld().getBlockState(e.getPos());
        ModEntityPlayerMP p = (ModEntityPlayerMP) e.getPlayer();
        BlockPos pos = e.getPos();
        if(BlockTags.DOORS.contains(state.getBlock()) && state.get(DoorBlock.HALF) == DoubleBlockHalf.UPPER)
        {
            pos = pos.add(0, -1, 0);
        }
        if(!bank.hasAccess(pos, e.getWorld(), p) && !perms.hasPermission(p, BLOCK_BYPASS))
        {
            e.setCanceled(true);   
        }  
    }
}
