use bevy::{
    prelude::*,
    render::mesh::{Indices, VertexAttributeValues},
};
use bevy_polyline::prelude::{Polyline, PolylineBundle, PolylineMaterial, PolylinePlugin};
use rand::{thread_rng, Rng};

use crate::{lights::AnimateCyberLightWireframe, planet::CyberPlanet};

pub const BISEXY_COLOR: Color = Color::hsla(292.0, 0.9, 0.60, 1.1);

fn wireframe_planet(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut polylines: ResMut<Assets<Polyline>>,
    mut polymats: ResMut<Assets<PolylineMaterial>>,
    query: Query<&Handle<Mesh>, With<CyberPlanet>>,
) {
    let handle = query.single();
    let mesh = meshes.get_mut(handle).unwrap();
    let vertices = mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();

    let mut pts = Vec::with_capacity(vertices.len());

    if let VertexAttributeValues::Float32x3(verts) = vertices {
        let indices = mesh.indices().unwrap();
        if let Indices::U32(indices) = indices {
            for i in indices.iter() {
                let v = verts[*i as usize];
                let v = Vec3::from_slice(&v);
                pts.push(v);
            }
        }
    }

    let mut verts = Vec::with_capacity((pts.len() as f32 * 1.4) as usize);
    for pts in pts.chunks(3) {
        if pts.len() > 1 {
            verts.extend_from_slice(pts);
            verts.push(Vec3::NAN);
        }
    }

    // don't need the indices anymore
    mesh.duplicate_vertices();
    mesh.compute_flat_normals();

    commands.spawn(PolylineBundle {
        polyline: polylines.add(Polyline { vertices: verts }),
        material: polymats.add(PolylineMaterial {
            width: 101.0,
            color: BISEXY_COLOR,
            perspective: true,
            depth_bias: -0.001,
        }),
        ..Default::default()
    });
}

fn wireframify_lights(mut lights: Query<&mut AnimateCyberLightWireframe>) {
    let chance = 0.005;

    let rng = &mut thread_rng();

    for mut light in lights.iter_mut() {
        if rng.gen::<f32>() < chance {
            let new = !light.wired;
            light.wired = new;
        }
    }
}

// public plugin
pub struct CyberGlamorPlugin;
impl Plugin for CyberGlamorPlugin {
    fn build(&self, app: &mut App) {
        #[cfg(feature = "inspector")]
        {
            use bevy_rapier3d::render::{
                DebugRenderMode, DebugRenderStyle, RapierDebugRenderPlugin,
            };
            let style = DebugRenderStyle {
                multibody_joint_anchor_color: Color::GREEN.as_rgba_f32(),
                ..Default::default()
            };
            let mode = DebugRenderMode::CONTACTS
                | DebugRenderMode::SOLVER_CONTACTS
                | DebugRenderMode::JOINTS
                | DebugRenderMode::RIGID_BODY_AXES;

            let rplugin = RapierDebugRenderPlugin {
                style,
                always_on_top: true,
                enabled: true,
                mode,
            };

            app.add_plugin(rplugin);
        }

        app.add_startup_system_to_stage(StartupStage::PostStartup, wireframe_planet)
            .add_system(wireframify_lights)
            .add_plugin(PolylinePlugin);
    }
}
