use strafesnet_graphics::graphics;
use strafesnet_session::session;
use strafesnet_settings::settings;

pub enum Instruction{
	Render(session::FrameState),
	//UpdateModel(graphics::GraphicsModelUpdate),
	Resize(winit::dpi::PhysicalSize<u32>,settings::UserSettings),
	ChangeMap(strafesnet_common::map::CompleteMap),
}

//Ideally the graphics thread worker description is:
/*
WorkerDescription{
	input:Immediate,
	output:Realtime(PoolOrdering::Ordered(3)),
}
*/
//up to three frames in flight, dropping new frame requests when all three are busy, and dropping output frames when one renders out of order

pub fn new(
	mut graphics:graphics::GraphicsState,
	mut surface:strafesnet_graphics::surface::Surface<'_>,
	device:wgpu::Device,
	queue:wgpu::Queue,
)->crate::compat_worker::INWorker<'_,Instruction>{
	crate::compat_worker::INWorker::new(move |ins:Instruction|{
		match ins{
			Instruction::ChangeMap(map)=>{
				graphics.clear();
				graphics.generate_models(&device,&queue,&map);
			},
			Instruction::Resize(size,user_settings)=>{
				println!("Resizing to {:?}",size);
				let t0=std::time::Instant::now();
				let size=glam::uvec2(size.width,size.height);
				surface.configure(&device,size);
				let size=surface.size();
				let fov=user_settings.calculate_fov(1.0,&size).as_vec2();
				graphics.resize(&device,size,fov);
				println!("Resize took {:?}",t0.elapsed());
			}
			Instruction::Render(frame_state)=>{
				//this has to go deeper somehow
				let frame=surface.new_frame(&device).expect("Error creating new frame");

				let mut encoder=device.create_command_encoder(&wgpu::CommandEncoderDescriptor{label:None});

				graphics.encode_commands(&mut encoder,frame.view(),graphics::view_inv(frame_state.pos(),frame_state.angles()));

				queue.submit([encoder.finish()]);

				frame.present();
			}
		}
	})
}
