/*
            player.rect.x += 1;
            player.rect.y += 1;
            let mut touched = vec![];
            for (wi,w) in walls.iter().enumerate() {
                if let Some(disp) = player.rect.disp(w.rect) {
                    touched.push((wi,disp));
                }
            }
            touched.sort_by_key(|(_,(dx,dy))| -dx.abs().min(dy.abs()));
            let mut movement = (0,0);
            let mut real_touches = vec![];
            for (idx,(dx,dy)) in touched.into_iter() {
                let (dx1,dy1) = (dx+movement.0,dy+movement.1);
                if dx1 == 0 || dy1 == 0 { continue; }
                if dx1 < dy1 {
                    movement.0 -= dx1;
                    player.rect.x = 0.max(player.rect.x as isize - dx1).min(WIDTH as isize-1) as usize;
                    real_touches.push((idx,(dx1,0)));
                } else {
                    movement.1 -= dy1;
                    player.rect.y = 0.max(player.rect.y as isize - dy1).min(HEIGHT as isize-1) as usize;
                    real_touches.push((idx,(0,dy1)));
                }
            }
*/


impl Rect {
    fn disp(&self, r2:Self) -> Option<(isize,isize)> {
        // Draw this out on paper to double check, but these quantities
        // will both be positive exactly when the conditions in rect_touching are true.
        let x_overlap = (self.x+self.w).min(r2.x+r2.w) as isize - self.x.max(r2.x) as isize;
        let y_overlap = (self.y+self.h).min(r2.y+r2.h) as isize - self.y.max(r2.y) as isize;
        if x_overlap >= 0 && y_overlap >= 0 {
            // This will return the magnitude of overlap in each axis.
            Some((x_overlap, y_overlap))
        } else {
            None
        }
    }
}
fn gather_contacts(statics: &[Wall], dynamics:&[Mobile], into:&mut Vec<Contact>) {
    // collide mobiles against mobiles
    for (ai,a) in dynamics.iter().enumerate() {
        for (bi,b) in dynamics[(ai+1)..].iter().enumerate() {
            if let Some(disp) = rect_displacement(a.rect, b.rect) {
                into.push(Contact{a:ColliderID::Dynamic(ai), b:ColliderID::Dynamic(bi), mtv:disp});
            }
        }
    }
    // collide mobiles against walls
    for (ai,a) in dynamics.iter().enumerate() {
        for (bi,b) in statics.iter().enumerate() {
            if let Some(disp) = rect_displacement(a.rect, b.rect) {
                into.push(Contact{a:ColliderID::Dynamic(ai), b:ColliderID::Static(bi), mtv:disp});
            }
        }
    }
}

fn restitute(statics: &[Wall], dynamics:&mut [Mobile], contacts:&mut [Contact]) {
    // handle restitution of dynamics against dynamics and dynamics against statics wrt contacts
    // You could instead make contacts `&mut [Contact]` if you want to modify or sort it in place or even `Vec<Contact>` if you think you might remove contacts.
    // You could also add an additional parameter, a slice or vec representing how far we've displaced each dynamic, to avoid allocations if you track a vec of how far things have been moved.
    // You might also want to pass in another &mut Vec<Contact> to be filled in with "real" touches that actually happened.
    contacts.sort_unstable_by_key(|c| -(c.mtv.0*c.mtv.0+c.mtv.1*c.mtv.1));
    let mut disps:Vec<(i32,i32)> = dynamics.iter().map(|_| (0,0)).collect();
    for c in contacts.iter() {
        // we know c.a is dynamic
        // c.b might or might not be
        // for now ignore dynamic-dynamic collision
        match (c.a, c.b) {
            (ColliderID::Dynamic(_a), ColliderID::Dynamic(_b)) => todo!(),
            (ColliderID::Dynamic(a), ColliderID::Static(b)) => {
                let mtv = (c.mtv.0 + disps[a].0, c.mtv.1 + disps[a].1);
                if mtv.0 == 0 || mtv.1 == 0 { continue; }
                if mtv.0 <= mtv.1 {
                    if statics[b].rect.x+statics[b].rect.w as i32/2 < dynamics[a].rect.x+dynamics[a].rect.w as i32/2 {
                        disps[a].0 += mtv.0;
                        dynamics[a].rect.x += mtv.0;
                    } else {
                        disps[a].0 -= mtv.0;
                        dynamics[a].rect.x -= mtv.0;
                    }
                } else {
                    if statics[b].rect.y+statics[b].rect.h as i32/2 < dynamics[a].rect.y+dynamics[a].rect.h as i32/2 {
                        disps[a].1 += mtv.1;
                        dynamics[a].rect.y += mtv.1;
                    } else {
                        disps[a].1 -= mtv.1;
                        dynamics[a].rect.y -= mtv.1;
                    }
                }
            },
            (ColliderID::Static(_), _) => panic!(),
        }
    }
}