use glc::vector::{Angle, Vector2f, Vector4f};
use space_crush_common::{
    components::{Fleet, Position},
    constants::SHIP_ORBIT_DISTANCE_MAX,
};
use specs::{prelude::*, ReadStorage, System, World, WriteExpect};

use crate::resources::Geometry;

#[derive(Default)]
pub struct Fleets;

#[derive(SystemData)]
pub struct FleetData<'a> {
    geometry: WriteExpect<'a, Geometry>,
    position: ReadStorage<'a, Position>,
    fleet: ReadStorage<'a, Fleet>,
}

impl<'a> System<'a> for Fleets {
    type SystemData = FleetData<'a>;

    fn run(&mut self, data: Self::SystemData) {
        let FleetData {
            mut geometry,
            position,
            fleet,
        } = data;

        gl::enable(gl::BLEND);
        gl::blend_func(gl::SRC_ALPHA, gl::ONE);

        for (p, f) in (&position, &fleet).join() {
            geometry.render_lines(
                Vector4f::new(0.5, 0.5, 0.5, 0.05),
                &create_circle(p.pos, f.orbit_min),
            );
            geometry.render_lines(
                Vector4f::new(0.5, 0.5, 0.5, 0.05),
                &create_circle(p.pos, f.orbit_max),
            );
            geometry.render_lines(
                Vector4f::new(0.5, 0.5, 0.5, 0.05),
                &create_circle(p.pos, SHIP_ORBIT_DISTANCE_MAX * f.orbit_max),
            );
        }

        gl::disable(gl::BLEND);
    }
}

fn create_circle(p: Vector2f, r: f32) -> Vec<Vector2f> {
    let mut points = Vec::new();

    for i in 0..=180 {
        points.push(Vector2f::new(
            p.x + r * Angle::Deg(i as f32 * 2.0).cos(),
            p.y + r * Angle::Deg(i as f32 * 2.0).sin(),
        ));
    }

    points
}
