use avian3d::prelude::{
    AngularDamping, AngularVelocity, CoefficientCombine, Collider, ColliderDensity,
    CollisionLayers, ExternalTorque, Friction, LinearDamping, LinearVelocity, Restitution,
    RigidBody, SleepingDisabled,
};
use bevy::{
    core::Name,
    prelude::{
        AssetServer, BuildChildren, ChildBuild, Commands, Quat, Res, Transform, Vec3, Visibility,
    },
    scene::SceneRoot,
};

use super::{spawn_wheels, CyberBikeBody, Meshterial, WheelConfig};
use crate::{action::CatControllerState, planet::PLANET_RADIUS, ColliderGroups};

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 friction = Friction {
        dynamic_coefficient: 0.1,
        static_coefficient: 0.6,
        combine_rule: CoefficientCombine::Average,
    };

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

    let bike_collision_group =
        CollisionLayers::new(ColliderGroups::BikeBody, ColliderGroups::Planet);

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

    let body_collider =
        Collider::capsule_endpoints(0.5, Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8));
    let spatial_bundle = (xform, Visibility::default());
    let bike = commands
        .spawn(spatial_bundle)
        .insert((
            Name::new("bike body"),
            RigidBody::Dynamic,
            body_collider,
            bike_collision_group,
            restitution,
            friction,
            SleepingDisabled,
            CyberBikeBody,
            CatControllerState::default(),
            ColliderDensity(20.0),
            LinearDamping(0.1),
            AngularDamping(2.0),
            LinearVelocity::ZERO,
            AngularVelocity::ZERO,
            ExternalTorque::ZERO.with_persistence(false),
        ))
        .with_children(|rider| {
            rider.spawn(SceneRoot(scene));
        })
        .id();

    bevy::log::info!("bike body: {bike:?}");

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