use pumpkin_util::{
    math::{position::BlockPos, vector3::Vector3},
    random::{RandomGenerator, RandomImpl},
};

use crate::generation::proto_chunk::GenerationCache;
use crate::{generation::feature::placed_features::PlacedFeature, world::WorldPortalExt};

pub struct RandomPatchFeature {
    pub tries: u8,
    pub xz_spread: u8,
    pub y_spread: u8,
    pub feature: Box<PlacedFeature>,
}

impl RandomPatchFeature {
    #[expect(clippy::too_many_arguments)]
    pub fn generate<T: GenerationCache>(
        &self,
        chunk: &mut T,
        block_registry: &dyn WorldPortalExt,
        min_y: i8,
        height: u16,
        feature: pumpkin_data::placed_feature::PlacedFeature,
        random: &mut RandomGenerator,
        pos: BlockPos,
    ) -> bool {
        let xz = self.xz_spread as i32 + 1;
        let y = self.y_spread as i32 + 1;
        let mut is_some = false;
        for _ in 0..self.tries {
            let pos = Vector3::new(
                pos.0.x + random.next_bounded_i32(xz) - random.next_bounded_i32(xz),
                pos.0.y + random.next_bounded_i32(y) - random.next_bounded_i32(y),
                pos.0.z + random.next_bounded_i32(xz) - random.next_bounded_i32(xz),
            );
            if !self.feature.generate(
                chunk,
                block_registry,
                min_y,
                height,
                feature,
                random,
                BlockPos(pos),
            ) {
                continue;
            }
            is_some = true;
        }
        is_some
    }
}
