use crate::fw_error::Result;
use crate::fw_writer_schema::FwWriterSchema;

/// Shared state for [`FwWriter`](crate::FwWriter) and
/// [`AsyncFwWriter`](crate::AsyncFwWriter), holding the schema and
/// record-counter logic.
///
/// The sync and async writer wrappers call [`prepare_byte_record`](Self::prepare_byte_record)
/// (or [`prepare_string_record`](Self::prepare_string_record)) to format a
/// record into the schema's internal buffer, then perform a single
/// `write_all` of [`record_buffer`](Self::record_buffer).
#[derive(Debug)]
pub(crate) struct FwWriterState {
    schema: FwWriterSchema,
    record_number: u64,
    #[cfg(feature = "encoding_rs")]
    encoding: &'static encoding_rs::Encoding,
}

impl FwWriterState {
    #[must_use]
    pub fn new(
        schema: FwWriterSchema,
        #[cfg(feature = "encoding_rs")] encoding: &'static encoding_rs::Encoding,
    ) -> Self {
        Self {
            schema,
            record_number: 0,
            #[cfg(feature = "encoding_rs")]
            encoding,
        }
    }

    #[must_use]
    pub fn record_number(&self) -> u64 {
        self.record_number
    }

    #[must_use]
    pub fn record_buffer(&self) -> &[u8] {
        self.schema.record_buffer()
    }

    /// Formats a byte record into the schema's internal buffer.
    pub fn prepare_byte_record(&mut self, values: &[&[u8]]) -> Result<()> {
        self.schema.prepare_byte_record(values)?;
        self.record_number += 1;
        Ok(())
    }

    /// Formats a string record into the schema's internal buffer.
    #[cfg(feature = "encoding_rs")]
    pub fn prepare_string_record(&mut self, values: &[&str]) -> Result<()> {
        self.schema.prepare_string_record(values, self.encoding)?;
        self.record_number += 1;
        Ok(())
    }

    #[must_use]
    pub fn for_schema(self, schema: FwWriterSchema) -> (Self, FwWriterSchema) {
        let old_schema = self.schema;
        let new_state = Self {
            schema,
            record_number: self.record_number,
            #[cfg(feature = "encoding_rs")]
            encoding: self.encoding,
        };
        (new_state, old_schema)
    }
}
