use std::fmt;

#[derive(Clone, Copy)]
pub enum Indent {
    Pretty { step: usize, current: usize },
    Compact,
}

impl Default for Indent {
    fn default() -> Self {
        Indent::Pretty {
            step: 4,
            current: 0,
        }
    }
}

impl Indent {
    pub fn nested(self) -> Self {
        match self {
            Indent::Pretty { step, current } => Indent::Pretty {
                step,
                current: current + step,
            },
            Indent::Compact => Indent::Compact,
        }
    }
}

pub fn pad(f: &mut impl fmt::Write, indentation: usize) -> fmt::Result {
    for _ in 0..indentation {
        write!(f, " ")?;
    }
    Ok(())
}

pub(crate) fn maybe_pad(f: &mut impl fmt::Write, indentation: Indent) -> fmt::Result {
    if let Indent::Pretty { current, .. } = indentation {
        pad(f, current)
    } else {
        Ok(())
    }
}

pub(crate) fn newline_or_space(f: &mut impl fmt::Write, indentation: Indent) -> fmt::Result {
    match indentation {
        Indent::Pretty { .. } => writeln!(f),
        Indent::Compact => write!(f, " "),
    }
}

pub(crate) fn maybe_newline(f: &mut impl fmt::Write, indentation: Indent) -> fmt::Result {
    match indentation {
        Indent::Pretty { .. } => writeln!(f),
        Indent::Compact => Ok(()),
    }
}

/// Writes a blank line separator in Pretty mode (two newlines), or a single space in Compact mode.
/// Use this for section breaks where Pretty mode wants visual separation via blank lines.
pub(crate) fn blank_line_or_space(f: &mut impl fmt::Write, indentation: Indent) -> fmt::Result {
    match indentation {
        Indent::Pretty { .. } => {
            writeln!(f)?;
            writeln!(f)
        }
        Indent::Compact => write!(f, " "),
    }
}
