use crate::components::{self, Position, Sprite};
use crate::consts;
use crate::game::MyGame;

use ggez::{graphics, graphics::spritebatch::SpriteBatch, Context};
use specs::RunNow;

/// The `Draw` system is parameterized by which phase we want to draw
/// in.
pub struct Draw<'t, Phase> {
    pub ctx: &'t mut Context,
    //pub sprites: &'t mut SpriteBatch,
    pub _phase: Phase,
}

impl<'a, 't, Phase: specs::Component> specs::System<'a> for Draw<'t, Phase> {
    type SystemData = (
        specs::ReadStorage<'a, Position>,
        specs::ReadStorage<'a, Sprite>,
        specs::ReadStorage<'a, Phase>,
        specs::WriteExpect<'a, SpriteBatch>,
    );

    fn run(&mut self, (positions, sprites, phase, mut batch): Self::SystemData) {
        use specs::Join;

        for (pos, spr, _) in (&positions, &sprites, &phase).join() {
            let param = graphics::DrawParam {
                src: spr.to_rect(),
                dest: pos.to_point(),
                scale: mint::Vector2 {
                    x: consts::SCALE,
                    y: consts::SCALE,
                },
                ..Default::default()
            };
            batch.add(param);
        }
        let basic: graphics::DrawParam = Default::default();
        graphics::draw(self.ctx, &*batch, basic).unwrap();
        batch.clear();
    }
}

pub fn systems(game: &mut MyGame, ctx: &mut Context) -> ggez::GameResult<()> {
    graphics::clear(ctx, graphics::BLACK);

    Draw {
        ctx,
        _phase: components::Background,
    }
    .run_now(&game.world);
    Draw {
        ctx,
        _phase: components::Foreground,
    }
    .run_now(&game.world);
    Draw {
        ctx,
        _phase: components::Decoration,
    }
    .run_now(&game.world);

    graphics::present(ctx)
}
