package jesse.keeblarcraft.CustomBlocks.Blocks;

import org.jetbrains.annotations.Nullable;

import jesse.keeblarcraft.CustomBlocks.BlockEntities.BlockEntityRegistration;
import jesse.keeblarcraft.CustomBlocks.BlockEntities.FactionBlockEntity;
import jesse.keeblarcraft.FactionMgr.FactionManager;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;

public class FactionBaseBlock extends BlockWithEntity implements BlockEntityProvider {
    // public static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 12, 16);
    private String faction; // Faction attached to this block

    public FactionBaseBlock(Settings settings) {
        super(settings);
    }

    // @Override
    // protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
    //     return SHAPE;
    // }

    @Override
    public BlockRenderType getRenderType(BlockState state) {
        return BlockRenderType.MODEL;
    }

    @Override
    public void onPlaced(World world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {
        if (world.isClient()) {
            return;
        }

        if (placer.isPlayer()) {
            // We need to run faction checks here and make sure this player owns a faction otherwise they are NOT allowed to place it!
            ServerPlayerEntity player = (ServerPlayerEntity) placer;
            String fac = FactionManager.GetInstance().GetFactionOfPlayer(player.getUuidAsString());

            FactionBlockEntity bEntity = (FactionBlockEntity) world.getBlockEntity(pos);

            // Update block entity
            if (bEntity != null) {
                bEntity.SetFaction(fac);
            }

            // An empty string implies NO faction; only do things if it is NOT empty
            if (!fac.equals("")) {
                faction = fac;
                player.sendMessage(Text.of("This block now belongs to the " + faction + " faction."));
            } else {
                player.sendMessage(Text.of("You do not appear to be in a faction, and thus this block cannot be placed!"));
                // world.removeBlock(pos, false);
                world.breakBlock(pos, true);
            }
        }
    }

    @Override
    public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
        return new FactionBlockEntity(pos, state, faction);
    }

    // If block is destroyed; drop inventory
    @Override
    public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
        if (state.getBlock() != newState.getBlock()) {
            BlockEntity blockEntity = world.getBlockEntity(pos);
            if (blockEntity != null && blockEntity instanceof FactionBlockEntity) {
                ItemScatterer.spawn(world, pos, (FactionBlockEntity) blockEntity);
                world.updateComparators(pos, this);
            }

            // This is pulled directly from #AbstractBlock$AbstractBlockState.class:onStateReplaced
            // Catch if the block is being broken. Update our block entity to reset all
            if (state.hasBlockEntity() && !state.isOf(newState.getBlock())) {
                FactionBlockEntity bEntity = (FactionBlockEntity) world.getBlockEntity(pos);
                if (bEntity != null) {
                    bEntity.ResetBlock();
                }
            }

            super.onStateReplaced(state, world, pos, newState, moved);
        }
    }

    // Open the inventory
    // Calls ScreenHandler inside createMenu of entity class
    @Override
    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
        // Server side handling is different than that of client side handling; we MUST check if we are on a server first because then we must
        // request information about this block entity from the server
        System.out.println("onUse of faction base block called");
        if (!world.isClient()) {
            NamedScreenHandlerFactory screenHandlerFactory = (FactionBlockEntity) world.getBlockEntity(pos);

            if (screenHandlerFactory != null) {
                player.openHandledScreen(screenHandlerFactory);
            }
        }
        return ActionResult.SUCCESS;
    }

    @Override
    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
        return validateTicker(type, BlockEntityRegistration.FACTION_BLOCK_ENTITY,
        (world1, pos, state1, blockEntity) -> blockEntity.tick(world1, pos, state1));
    }
}
