use super::*;
use crate::globals::get_options;
use anyhow::{Result, anyhow};
use shared::core::geometry::Point2i;
use shared::core::sampler::{PaddedSobolSampler, RandomizeStrategy, SobolSampler, ZSobolSampler};

impl CreateSampler for SobolSampler {
    fn create(
        params: &ParameterDictionary,
        full_res: Point2i,
        loc: &FileLoc,
        _arena: &Arena,
    ) -> Result<Sampler> {
        let options = get_options();
        let nsamp = if let Some(n) = options.quick_render.then_some(1).or(options.pixel_samples) {
            n
        } else {
            params.get_one_int("pixelsamples", 16)?
        };

        let seed = params.get_one_int("seed", options.seed)?;

        let s = match params.get_one_string("randomization", "fastowen")?.as_str() {
            "none" => RandomizeStrategy::None,
            "permutedigits" => RandomizeStrategy::PermuteDigits,
            "fastowen" => RandomizeStrategy::FastOwen,
            "owen" => RandomizeStrategy::Owen,
            _ => {
                return Err(anyhow!("{}: Unknown randomization strategy for Sobol", loc));
            }
        };

        let sampler = Self::new(nsamp, full_res, s, Some(seed as u64));
        // arena.alloc(sampler);
        Ok(Sampler::Sobol(sampler))
    }
}

impl CreateSampler for PaddedSobolSampler {
    fn create(
        params: &ParameterDictionary,
        _full_res: Point2i,
        loc: &FileLoc,
        _arena: &Arena,
    ) -> Result<Sampler> {
        let options = get_options();
        let nsamp = if let Some(n) = options.quick_render.then_some(1).or(options.pixel_samples) {
            n
        } else {
            params.get_one_int("pixelsamples", 16)?
        };
        let seed = params.get_one_int("seed", options.seed)?;
        let s = match params.get_one_string("randomization", "fastowen")?.as_str() {
            "none" => RandomizeStrategy::None,
            "permutedigits" => RandomizeStrategy::PermuteDigits,
            "fastowen" => RandomizeStrategy::FastOwen,
            "owen" => RandomizeStrategy::Owen,
            _ => {
                return Err(anyhow!(
                    "{}: Unknown randomization strategy for ZSobol",
                    loc
                ));
            }
        };

        let sampler = Self::new(nsamp, s, Some(seed as u64));
        // arena.alloc(sampler);
        Ok(Sampler::PaddedSobol(sampler))
    }
}

impl CreateSampler for ZSobolSampler {
    fn create(
        params: &ParameterDictionary,
        full_res: Point2i,
        loc: &FileLoc,
        _arena: &Arena,
    ) -> Result<Sampler> {
        let options = get_options();
        let nsamp = if let Some(n) = options.quick_render.then_some(1).or(options.pixel_samples) {
            n
        } else {
            params.get_one_int("pixelsamples", 16)?
        };

        let seed = params.get_one_int("seed", options.seed)?;
        let s = match params.get_one_string("randomization", "fastowen")?.as_str() {
            "none" => RandomizeStrategy::None,
            "permutedigits" => RandomizeStrategy::PermuteDigits,
            "fastowen" => RandomizeStrategy::FastOwen,
            "owen" => RandomizeStrategy::Owen,
            _ => {
                return Err(anyhow!(
                    "{}: Unknown randomization strategy for ZSobol",
                    loc
                ));
            }
        };

        let sampler = ZSobolSampler::new(nsamp, full_res, s, Some(seed as u64));
        // arena.alloc(sampler);
        Ok(Sampler::ZSobol(sampler))
    }
}
