Documentation
use crate::arr::{shape_iterator::ShapeIterator, vec::core::ArrVec};
use std::fmt::{Debug, Display};

fn right_pading(value: &String, nchar: usize) -> String {
    let mut padding = String::new();
    while padding.len() < nchar - value.len() {
        padding.push_str(" ")
    }
    let mut out = value.clone();
    out.push_str(&padding);
    out
}

impl<T> Display for ArrVec<T>
where
    T: Display + Copy + Ord + Default,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let shape_len = self.shape.len();
        let max_result = self.buff.iter().max();
        let min_result = self.buff.iter().min();
        if max_result.is_none() || min_result.is_none() {
            return write!(f, "[]");
        }
        let min_value = min_result.unwrap();
        let max_value = max_result.unwrap();
        let max_str = max_value.to_string();
        let min_str = min_value.to_string();

        let there_is_negatives = *min_value < T::default();

        let item_len = if there_is_negatives && min_str.len() > max_str.len()  {
            min_str.len()
        } else if there_is_negatives {
            max_str.len() + 1
        } else {
            max_str.len()
        };

        for index in ShapeIterator::new(&self.shape) {
            for dim in 0..shape_len {
                if index[dim..shape_len].iter().any(|x| *x != 0_usize) {
                    continue;
                }
                for _ in 0..dim {
                    let res = write!(f, "  ");
                    if res.is_err() {
                        return res;
                    }
                }
                let res = write!(f, "[");
                if res.is_err() {
                    return res;
                }
                if dim < shape_len - 1 {
                    let res = write!(f, "\n");
                    if res.is_err() {
                        return res;
                    }
                };
            }

            let item = self[&index];

            let res = if there_is_negatives && item >= T::default() {
                write!(f, " {}", right_pading(&(item.to_string()), item_len - 1))
            } else {
                write!(f, "{}", right_pading(&(item.to_string()), item_len))
            };
            if res.is_err() {
                return res;
            }
            if index[shape_len - 1] != self.shape[shape_len - 1] - 1 {
                let res = write!(f, " ");
                if res.is_err() {
                    return res;
                }
            }

            for dim in (0..shape_len).rev() {
                let dim_size = self.shape[dim];
                if index[dim] != dim_size - 1 {
                    break;
                }

                if dim != shape_len - 1 {
                    let res = write!(f, "\n");
                    if res.is_err() {
                        return res;
                    }
                    for _ in 0..dim {
                        let res = write!(f, "  ");
                        if res.is_err() {
                            return res;
                        }
                    }
                }

                let res = write!(f, "]");
                if res.is_err() {
                    return res;
                }
                if dim > 0 && (index[dim - 1] != self.shape[dim - 1] - 1) {
                    let res = write!(f, "\n");
                    if res.is_err() {
                        return res;
                    }
                }
            }
        }
        Ok(())
    }
}

impl<T> Debug for ArrVec<T>
where
    T: Debug,
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ArrVec")
            .field("buff", &self.buff)
            .field("shape", &self.shape)
            .finish()
    }
}