#[derive(Clone,Debug)]
pub struct TimedInstruction<I,T>{
	pub time:T,
	pub instruction:I,
}
impl<I,T> TimedInstruction<I,T>{
	#[inline]
	pub fn set_time<T2>(self,new_time:T2)->TimedInstruction<I,T2>{
		TimedInstruction{
			time:new_time,
			instruction:self.instruction,
		}
	}
}

/// Ensure all emitted instructions are processed before consuming external instructions
pub trait InstructionEmitter<I>{
	type Time;
	fn next_instruction(&self,time_limit:Self::Time)->Option<TimedInstruction<I,Self::Time>>;
}
/// Apply an atomic state update
pub trait InstructionConsumer<I>{
	type Time;
	fn process_instruction(&mut self,instruction:TimedInstruction<I,Self::Time>);
}
/// If the object produces its own instructions, allow exhaustively feeding them back in
pub trait InstructionFeedback<I,T>:InstructionEmitter<I,Time=T>+InstructionConsumer<I,Time=T>
	where
		T:Copy,
{
	#[inline]
	fn process_exhaustive(&mut self,time_limit:T){
		while let Some(instruction)=self.next_instruction(time_limit){
			self.process_instruction(instruction);
		}
	}
	#[inline]
	fn into_iter(self,time_limit:T)->InstructionIter<I,T,Self>
		where
			Self:Sized
	{
		InstructionIter{
			time_limit,
			feedback:self,
			_phantom:core::marker::PhantomData,
		}
	}
}
impl<I,T,F> InstructionFeedback<I,T> for F
	where
		T:Copy,
		F:InstructionEmitter<I,Time=T>+InstructionConsumer<I,Time=T>,
{}
pub struct InstructionIter<I,T:Copy,F:InstructionFeedback<I,T>>{
	time_limit:T,
	feedback:F,
	_phantom:core::marker::PhantomData<I>,
}
impl<I,T,F> Iterator for InstructionIter<I,T,F>
	where
		I:Clone,
		T:Clone+Copy,
		F:InstructionFeedback<I,T>,
{
	type Item=TimedInstruction<I,T>;
	fn next(&mut self)->Option<Self::Item>{
		let instruction=self.feedback.next_instruction(self.time_limit)?;
		self.feedback.process_instruction(instruction.clone());
		Some(instruction)
	}
}

//PROPER PRIVATE FIELDS!!!
pub struct InstructionCollector<I,T>{
	time:T,
	instruction:Option<I>,
}
impl<I,T> InstructionCollector<I,T>{
	#[inline]
	pub const fn new(time:T)->Self{
		Self{
			time,
			instruction:None
		}
	}
	#[inline]
	pub fn take(self)->Option<TimedInstruction<I,T>>{
		//STEAL INSTRUCTION AND DESTROY INSTRUCTIONCOLLECTOR
		self.instruction.map(|instruction|TimedInstruction{
			time:self.time,
			instruction
		})
	}
}
impl<I,T:Copy> InstructionCollector<I,T>{
	#[inline]
	pub const fn time(&self)->T{
		self.time
	}
}
impl<I,T:PartialOrd> InstructionCollector<I,T>{
	#[inline]
	pub fn collect(&mut self,instruction:Option<TimedInstruction<I,T>>){
		if let Some(ins)=instruction{
			if ins.time<self.time{
				self.time=ins.time;
				self.instruction=Some(ins.instruction);
			}
		}
	}
}
