use crate::err::{SJFLError, Span};
use super::{Parse, Session};

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct InternedString {
    pub index: u32
}

impl Parse for InternedString {

    fn parse(s: &[u8], mut ind: usize, session: &mut Session) -> Result<(Self, usize), SJFLError> {
        let marker = s[ind];

        if marker != b'\'' && marker != b'"' {
            return Err(SJFLError::UnexpectedChar(marker, Span::from_index(ind)));
        }

        let mut buffer = vec![];

        let mut escaped = false;
        ind += 1;

        loop {

            if ind >= s.len() {
                return Err(SJFLError::UnexpectedEof(Span::from_index(ind)));
            }

            if !escaped && s[ind] == marker {
                return Ok((InternedString { index: session.intern_string(&buffer) }, ind + 1));
            }

            if !escaped && s[ind] == b'\\' {
                escaped = true;
            }

            else if escaped {

                if s[ind] == b'n' {
                    buffer.push(b'\n');
                }

                else if s[ind] == b'r' {
                    buffer.push(b'\r');
                }

                else if s[ind] == b't' {
                    buffer.push(b'\t');
                }

                else {
                    buffer.push(s[ind]);
                }

                escaped = false;
            }

            else {
                buffer.push(s[ind]);
            }

            ind += 1;
        }

    }

}