use std::io::Read;

mod rbx;
mod mesh;
mod primitives;

pub mod data{
	pub struct RobloxMeshBytes(Vec<u8>);
	impl RobloxMeshBytes{
		pub fn new(bytes:Vec<u8>)->Self{
			Self(bytes)
		}
		pub fn cursor(self)->std::io::Cursor<Vec<u8>>{
			std::io::Cursor::new(self.0)
		}
	}
}

pub struct Dom(rbx_dom_weak::WeakDom);

#[derive(Debug)]
pub enum ReadError{
	RbxBinary(rbx_binary::DecodeError),
	RbxXml(rbx_xml::DecodeError),
	Io(std::io::Error),
	UnknownFileFormat,
}
impl std::fmt::Display for ReadError{
	fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
		write!(f,"{self:?}")
	}
}
impl std::error::Error for ReadError{}

pub fn read<R:Read>(input:R)->Result<Dom,ReadError>{
	let mut buf=std::io::BufReader::new(input);
	let peek=std::io::BufRead::fill_buf(&mut buf).map_err(ReadError::Io)?;
	match &peek[0..8]{
		b"<roblox!"=>rbx_binary::from_reader(buf).map(Dom).map_err(ReadError::RbxBinary),
		b"<roblox "=>rbx_xml::from_reader_default(buf).map(Dom).map_err(ReadError::RbxXml),
		_=>Err(ReadError::UnknownFileFormat),
	}
}

//ConvertError

pub fn convert<AcquireRenderConfigId,AcquireMeshId>(
	dom:&Dom,
	acquire_render_config_id:AcquireRenderConfigId,
	acquire_mesh_id:AcquireMeshId
)->rbx::PartialMap1
where
	AcquireRenderConfigId:FnMut(Option<&str>)->strafesnet_common::model::RenderConfigId,
	AcquireMeshId:FnMut(&str)->strafesnet_common::model::MeshId,
{
	rbx::convert(&dom.0,acquire_render_config_id,acquire_mesh_id)
}