use binrw::{BinReaderExt, binrw};

#[derive(Debug)]
pub enum Error{
	InvalidHeader,
	InvalidSegment(binrw::Error),
	InvalidSegmentId(SegmentId),
	File(crate::file::Error),
}

/* block types

BLOCK_BOT_HEADER:
u128 map_resource_uuid //which map is this bot running
//don't include style info in bot header because it's in the simulation state
//blocks are laid out in chronological order, but indices may jump around.
u64 num_segments
for _ in 0..num_segments{
	i64 time //simulation_state timestamp
	u64 block_id
}

BLOCK_BOT_SEGMENT:
//format version indicates what version of these structures to use
SimulationState simulation_state //SimulationState is just under ClientState which includes Play/Pause events that the simulation doesn't know about.
//to read, greedily decode instructions until eof
loop{
	//delta encode as much as possible (time,mousepos)
	//strafe ticks are implied
	//physics can be implied in an input-only bot file
	TimedInstruction<SimulationInstruction> instruction
}

*/

//error hiding mock code
mod simulation{
	#[super::binrw]
	#[brw(little)]
	pub struct State{}
	#[super::binrw]
	#[brw(little)]
	pub struct Instruction{}
}
// mod instruction{
	// #[super::binrw]
	// #[brw(little)]
	// pub struct TimedInstruction<Instruction:binrw::BinRead+binrw::BinWrite>{
		// time:u64,
		// instruction:Instruction
	// }
// }
// mod timeline{
	// #[super::binrw]
	// #[brw(little)]
	// pub struct Timeline<Instruction:binrw::BinRead+binrw::BinWrite>{
		// #[bw(try_calc(u32::try_from(instructions.len())))]
		// instruction_count:u32,
		// #[br(count=instruction_count)]
		// instructions:Vec<super::instruction::TimedInstruction<Instruction>>
	// }
// }

//serious code

#[binrw]
#[brw(little)]
#[derive(Clone,Copy,Debug,id::Id)]
pub struct SegmentId(u32);

#[binrw]
#[brw(little)]
pub struct Segment{
	state:simulation::State,
	//#[bw(try_calc(u32::try_from(instructions.len())))]
	//instruction_count:u32,
	//#[br(count=instruction_count)]
	//instructions:Vec<instruction::TimedInstruction<simulation::Instruction>>

	//please remember that strafe ticks are implicit! 33% smaller bot files
}

pub struct StreamableBot<R:BinReaderExt>{
	file:crate::file::File<R>,
	//timeline:timeline::Timeline<SegmentId>,
	segment_id_to_block_id:Vec<crate::file::BlockId>,
}
impl<R:BinReaderExt> StreamableBot<R>{
	pub(crate) fn new(file:crate::file::File<R>)->Result<Self,Error>{
		Err(Error::InvalidHeader)
	}
	pub fn load_segment(&mut self,segment_id:SegmentId)->Result<Segment,Error>{
		let block_id=*self.segment_id_to_block_id.get(segment_id.get() as usize).ok_or(Error::InvalidSegmentId(segment_id))?;
		let mut block=self.file.block_reader(block_id).map_err(Error::File)?;
		let segment=block.read_le().map_err(Error::InvalidSegment)?;
		Ok(segment)
	}
}
