use bevy::{
    prelude::{AssetServer, BuildChildren, Commands, Quat, Res, SpatialBundle, Transform, Vec3},
    scene::SceneBundle,
};
use bevy_rapier3d::prelude::{
    Ccd, Collider, ColliderMassProperties, CollisionGroups, Damping, ExternalForce, Friction,
    ReadMassProperties, Restitution, RigidBody, Sleeping, TransformInterpolation, Velocity,
};

use super::{spawn_tires, CyberBikeBody, Meshterial, WheelConfig, BIKE_BODY_COLLISION_GROUP};
use crate::{action::CatControllerState, planet::PLANET_RADIUS};

pub(super) fn spawn_cyberbike(
    mut commands: Commands,
    asset_server: Res<AssetServer>,
    wheel_conf: Res<WheelConfig>,
    mut meshterials: Meshterial,
) {
    let altitude = PLANET_RADIUS + 10.0;

    let mut xform = Transform::from_translation(Vec3::X * altitude)
        .with_rotation(Quat::from_axis_angle(Vec3::Z, -89.0f32.to_radians()));

    let right = xform.right() * 350.0;
    xform.translation += right;

    let damping = Damping {
        angular_damping: 2.0,
        linear_damping: 0.1,
    };

    let friction = Friction {
        coefficient: 0.3,
        ..Default::default()
    };

    let restitution = Restitution {
        coefficient: 0.0,
        ..Default::default()
    };

    let mass_properties = ColliderMassProperties::Density(0.9);

    let (membership, filter) = BIKE_BODY_COLLISION_GROUP;
    let bike_collision_group = CollisionGroups::new(membership, filter);

    let scene = asset_server.load("cb-no-y_up.glb#Scene0");

    let spatialbundle = SpatialBundle {
        transform: xform,
        ..Default::default()
    };

    let bike = commands
        .spawn(RigidBody::Dynamic)
        .insert(spatialbundle)
        .insert((
            Collider::capsule(Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8), 0.50),
            bike_collision_group,
            mass_properties,
            damping,
            restitution,
            friction,
            Sleeping::disabled(),
            Ccd { enabled: true },
            ReadMassProperties::default(),
        ))
        .insert(TransformInterpolation {
            start: None,
            end: None,
        })
        .insert(Velocity::zero())
        .insert(ExternalForce::default())
        .with_children(|rider| {
            rider.spawn(SceneBundle {
                scene,
                ..Default::default()
            });
        })
        .insert(CyberBikeBody)
        .insert(CatControllerState::default())
        .id();

    spawn_tires(&mut commands, &xform, bike, &wheel_conf, &mut meshterials);
}
