use pumpkin_data::BlockStateId;
use pumpkin_data::{Block, BlockDirection};
use pumpkin_macros::pumpkin_block;

use crate::block::{
    BlockBehaviour, BlockFuture, CanPlaceAtArgs, CanUpdateAtArgs, GetStateForNeighborUpdateArgs,
    OnPlaceArgs,
};

use super::segmented::Segmented;

type LeafLitterProperties = pumpkin_data::block_properties::LeafLitterLikeProperties;

#[pumpkin_block("minecraft:leaf_litter")]
pub struct LeafLitterBlock;

impl BlockBehaviour for LeafLitterBlock {
    fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
        let block_below = args.block_accessor.get_block_state(&args.position.down());
        block_below.is_side_solid(BlockDirection::Up)
    }

    fn can_update_at(&self, args: CanUpdateAtArgs<'_>) -> bool {
        Segmented::can_update_at(self, args)
    }

    fn on_place<'a>(&'a self, args: OnPlaceArgs<'a>) -> BlockFuture<'a, BlockStateId> {
        Box::pin(async move { Segmented::on_place(self, args).await })
    }

    fn get_state_for_neighbor_update<'a>(
        &'a self,
        args: GetStateForNeighborUpdateArgs<'a>,
    ) -> BlockFuture<'a, BlockStateId> {
        Box::pin(async move {
            if args.direction == BlockDirection::Down {
                let block_below_state = args.world.get_block_state(&args.position.down());
                if !block_below_state.is_side_solid(BlockDirection::Up) {
                    return Block::AIR.default_state.id;
                }
            }
            args.state_id
        })
    }
}

impl Segmented for LeafLitterBlock {
    type Properties = LeafLitterProperties;
}
