use num_traits::{Float, FromPrimitive, One, Zero};

use crate::smooth::SmoothError;

pub fn sma<T>(data: &mut [T], period: usize) -> Result<(), SmoothError>
where
    T: Float + FromPrimitive + Zero + Clone + One,
{
    let len = data.len();
    if period == 0 || len == 0 {
        return Err(SmoothError::SMAApplyError);
    }

    let half = period / 2;

    let left_padding = data[0];
    let right_padding = data[len - 1];
    let mut cache_sum = data[0] * T::from(half).unwrap();
    for i in 0..half {
        cache_sum = cache_sum + data[i];
    }

    data[0] = cache_sum / T::from(period).unwrap();

    for i in 0..len {
        let left;
        let right;
        if i < half {
            left = left_padding;
            right = data[i + half];
        } else if i > len - half -1 {
            left = data[i - half];
            right = right_padding;
        } else {
            left = data[i - half];
            right = data[i + half];
        }
        cache_sum = cache_sum + right - left;
        let p = if let Some(d) = T::from(period){
            d
        }else{
            return Err(SmoothError::SMAApplyError);
        };
        data[i] = cache_sum / p;
    }

    Ok(())
}
