use crate::escape::{ControlSequence, SetWindowParameter};

pub enum OscState {
    Ps(u32),
    Pt(u32, String),
    PtEsc(u32, String),
}

impl OscState {
    pub(super) const fn new() -> Self {
        Self::Ps(0)
    }

    pub(super) fn push(&mut self, ch: char) -> (Option<ControlSequence>, bool) {
        match self {
            Self::Ps(ps) if ch.is_ascii_digit() => {
                *ps *= 10;
                *ps += (ch as u8 - b'0') as u32;
                (None, false)
            }
            Self::Ps(ps) if ch == ';' => {
                *self = Self::Pt(*ps, String::new());
                (None, false)
            }
            // OSC Ps ; Pt BEL
            Self::Pt(ps, pt) if ch == '\x07' => {
                let pt = core::mem::take(pt);
                let control = Self::handle_sequence(*ps, pt);
                (control, true)
            }
            // OSC Ps ; Pt ST
            Self::PtEsc(ps, pt) if ch == '\\' => {
                let pt = core::mem::take(pt);
                let control = Self::handle_sequence(*ps, pt);
                (control, true)
            }
            // OSC Ps ; Pt ST (Where ST = ESC \)
            Self::Pt(ps, pt) if ch == '\x1B' => {
                let pt = core::mem::take(pt);
                *self = Self::PtEsc(*ps, pt);
                (None, false)
            }
            Self::Pt(_, pt) => {
                pt.push(ch);
                (None, false)
            }
            _ => (None, true),
        }
    }

    fn handle_sequence(ps: u32, pt: String) -> Option<ControlSequence> {
        match ps {
            // Ps = 0 ⇒ Change Icon Name and Window Title to Pt
            0 => Some(ControlSequence::SetWindowParameter(
                SetWindowParameter::Both,
                pt,
            )),
            // Ps = 1 ⇒ Change Icon Name to Pt
            1 => Some(ControlSequence::SetWindowParameter(
                SetWindowParameter::Icon,
                pt,
            )),
            // Ps = 2 ⇒ Change Window Title to Pt
            2 => Some(ControlSequence::SetWindowParameter(
                SetWindowParameter::Title,
                pt,
            )),
            _ => None,
        }
    }
}
