use std::{borrow::Cow, io::Write};

pub type Bit = bool;

#[derive(Clone, Debug)]
pub struct Field {
    name: String,
    from: usize,
    to: usize,
}

impl Field {
    pub fn new(name: String, from: usize, to: usize) -> Self {
        assert!(from < to);
        Self { name, from, to }
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn from(&self) -> usize {
        self.from
    }

    pub fn to(&self) -> usize {
        self.to
    }

    pub fn size(&self) -> usize {
        self.to - self.from
    }

    pub fn extract_bits<'a>(
        &self,
        bytes: &'a [u8],
    ) -> Option<impl Iterator<Item = (usize, Bit)> + 'a> {
        if self.to <= bytes.len() * 8 {
            Some((self.from..self.to).map(move |index| {
                let byte = bytes[index / 8];
                let bit_index = 7 - (index% 8);
                let bit_value = (byte >> bit_index) & 1 == 1;
                (index, bit_value)
            }))
        } else {
            None
        }
    }

    fn extend(&mut self, new_to: usize) {
        assert!(self.to <= new_to);
        self.to = new_to;
    }
}

trait Consume: Iterator {
    fn consume(&mut self, value: Self::Item) -> Result<Self::Item, Option<Self::Item>>
    where
        Self::Item: PartialEq,
    {
        match self.next() {
            Some(v) if v == value => Ok(v),
            Some(v) => Err(Some(v)),
            None => Err(None),
        }
    }
}

impl<T: Iterator> Consume for T {}

#[derive(Clone, Copy, Debug)]
enum ParserState {
    Uninitialized,
    ExpectBorder,
    ExpectField,
    AllowEmpty,
}

#[derive(Clone, Copy, Debug)]
pub enum ParserError {
    ParsingFailed,
    UnexpectedEnd,
    InvalidBorder,
    WrongLineWidth,
    FieldExpected,
    BadField,
}

#[derive(Debug)]
pub(crate) struct Parser {
    state: Option<ParserState>,
    width: usize,
    from: usize,
    fields: Vec<Field>,
}

impl Parser {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self {
            state: Some(ParserState::Uninitialized),
            width: 0,
            from: 0,
            fields: Vec::new(),
        }
    }

    pub fn accept(&mut self, line: &str) -> Result<(), ParserError> {
        if let Some(state) = self.state.take() {
            let line = line.trim();

            if!line.is_empty() {
                self.state = Some(match state {
                    ParserState::Uninitialized => self.parse_border(line)?,
                    ParserState::ExpectBorder => self.accept_border(line)?,
                    ParserState::ExpectField => self.parse_fields(line)?,
                    ParserState::AllowEmpty => self.extend_field(line)?,
                });
            }

            Ok(())
        } else {
            Err(ParserError::ParsingFailed)
        }
    }

    pub fn finish(self) -> Result<Vec<Field>, ParserError> {
        match self.state {
            Some(ParserState::ExpectField) => Ok(self.fields),
            _ => Err(ParserError::UnexpectedEnd),
        }
    }

    fn parse_border(&mut self, line: &str) -> Result<ParserState, ParserError> {
        self.width = Parser::border_columns(line).map_err(|_| ParserError::InvalidBorder)?;
        Ok(ParserState::ExpectField)
    }

    fn accept_border(&mut self, line: &str) -> Result<ParserState, ParserError> {
        match Parser::border_columns(line) {
            Ok(width) if width == self.width => Ok(ParserState::ExpectField),
            Ok(_) => Err(ParserError::WrongLineWidth),
            Err(_) => Err(ParserError::InvalidBorder),
        }
    }

    fn parse_fields(&mut self, line: &str) -> Result<ParserState, ParserError> {
        let mut slots = line.split('|');