#[derive(Clone,Copy)]
pub struct Vector3(pub(crate)glam::Vec3A);

impl Vector3{
	pub const fn new(x:f32,y:f32,z:f32)->Self{
		Self(glam::vec3a(x,y,z))
	}
}

pub fn set_globals(lua:&mlua::Lua,globals:&mlua::Table)->Result<(),mlua::Error>{
	let vector3_table=lua.create_table()?;

	//Vector3.new
	vector3_table.raw_set("new",
		lua.create_function(|_,(x,y,z):(f32,f32,f32)|
			Ok(Vector3::new(x,y,z))
		)?
	)?;

	globals.set("Vector3",vector3_table)?;

	Ok(())
}

impl Into<rbx_types::Vector3> for Vector3{
	fn into(self)->rbx_types::Vector3{
		rbx_types::Vector3::new(self.0.x,self.0.y,self.0.z)
	}
}

impl From<rbx_types::Vector3> for Vector3{
	fn from(value:rbx_types::Vector3)->Vector3{
		Vector3::new(value.x,value.y,value.z)
	}
}

impl mlua::UserData for Vector3{
	fn add_fields<F:mlua::UserDataFields<Self>>(fields:&mut F){
		fields.add_field_method_get("magnitude",|_,this|Ok(this.0.length()));
		fields.add_field_method_get("x",|_,this|Ok(this.0.x));
		fields.add_field_method_set("x",|_,this,val|{
			this.0.x=val;
			Ok(())
		});
		fields.add_field_method_get("y",|_,this|Ok(this.0.y));
		fields.add_field_method_set("y",|_,this,val|{
			this.0.y=val;
			Ok(())
		});
		fields.add_field_method_get("z",|_,this|Ok(this.0.z));
		fields.add_field_method_set("z",|_,this,val|{
			this.0.z=val;
			Ok(())
		});
	}

	fn add_methods<M:mlua::UserDataMethods<Self>>(methods:&mut M){
		//methods.add_method("area",|_,this,()| Ok(this.length * this.width));

		methods.add_meta_function(mlua::MetaMethod::Add,|_,(this,val):(Self,Self)|Ok(Self(this.0+val.0)));
		methods.add_meta_function(mlua::MetaMethod::Div,|_,(this,val):(Self,mlua::Value)|{
			match val{
				mlua::Value::Integer(n)=>Ok(Self(this.0/(n as f32))),
				mlua::Value::Number(n)=>Ok(Self(this.0/(n as f32))),
				mlua::Value::UserData(ud)=>{
					let rhs:Vector3=ud.take()?;
					Ok(Self(this.0/rhs.0))
				},
				other=>Err(mlua::Error::runtime(format!("Attempt to divide Vector3 by {other:?}"))),
			}
		});
		methods.add_meta_function(mlua::MetaMethod::ToString,|_,this:Self|
			Ok(format!("Vector3.new({},{},{})",
				this.0.x,
				this.0.y,
				this.0.z,
			))
		);
	}
}

type_from_lua_userdata!(Vector3);
