//use strafesnet_common::model;
//use strafesnet_common::gameplay_modes;
use binrw::{BinReaderExt, binrw};

pub enum Error{
	InvalidHeader,
	InvalidBvhNodeId(BvhNodeId),
	InvalidRegion(binrw::Error),
	File(crate::file::Error),
}

/* block types

BLOCK_MAP_HEADER:
DefaultStyleInfo style_info
//bvh goes here
u64 num_nodes
//node 0 parent node is implied to be None
for node_id in 1..num_nodes{
	u64 parent_node
}

//NOTE: alternate realities are not necessary.
//portals/wormholes simply use an in-model and and out-model.
//skyboxes are inverted models with a special shader.

//ideally spacial blocks are sorted from distance to start zone
//texture blocks are inserted before the first spacial block they are used in
u64 num_spacial_blocks
for spacial_block_id in 0..num_spacial_blocks{
	u64 node_id
	u64 block_id //data block
	Aabb block_extents
}
//if the map file references external resources, num_resources = 0
u64 num_resources
for resource_id in 0..num_resources{
	u64 block_id
	u128 resource_id
}

BLOCK_MAP_RESOURCE:
Resource resource_type
//an individual one of the following:
	- model (Mesh)
	- shader (compiled SPIR-V)
	- image (JpegXL)
	- sound (Opus)
	- video (AV1)
	- animation (Trey thing)

BLOCK_MAP_REGION:
u64 num_models
for model_id in 0..num_models{
	u128 model_resource_uuid
	ModelInstance mode_instance
}

*/


//error hiding mock code
mod gameplay_modes{
	pub struct Modes{}
}
mod model{
	pub struct Mesh{}
	#[super::binrw]
	#[brw(little)]
	pub struct Model{}
}
mod image{
	pub struct Image{}
}

//serious code

struct ModelUuid(u128);
struct ImageUuid(u128);

#[binrw]
#[brw(little)]
#[derive(Clone,Copy,id::Id)]
pub struct BvhNodeId(u32);
struct BvhNode{
	//aabb
	//child
}
#[binrw]
#[brw(little)]
struct Region{
	#[bw(try_calc(u32::try_from(models.len())))]
	model_count:u32,
	#[br(count=model_count)]
	models:Vec<model::Model>,
}

pub struct StreamableMap<R:BinReaderExt>{
	file:crate::file::File<R>,
	//this includes every platform... move the unconstrained datas to their appropriate data block?
	modes:gameplay_modes::Modes,
	bvh:BvhNode,
	node_id_to_block_id:Vec<crate::file::BlockId>,
}
impl<R:BinReaderExt> StreamableMap<R>{
	pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{
		Err(Error::InvalidHeader)
	}
	pub fn load_node(&mut self,node_id:BvhNodeId)->Result<Vec<model::Model>,Error>{
		//load region from disk
		//parse the models and determine what resources need to be loaded
		//load resources into self.resources
		//return Region
		let block_id=*self.node_id_to_block_id.get(node_id.get() as usize).ok_or(Error::InvalidBvhNodeId(node_id))?;
		let mut block=self.file.take_block(block_id).map_err(Error::File)?;
		let region:Region=block.read_le().map_err(Error::InvalidRegion)?;
		Ok(region.models)
	}
	// pub fn load_resource(&mut self,resource_id:ResourceId)->Resource{
	// 	//
	// }
}