use crate::components::{Position, Renderable};
use crate::map;
use rltk::{Console, Rltk};
use specs::{Join, ReadExpect, ReadStorage, System};

pub struct DrawRenderables<'r> {
    pub ctx: &'r mut Rltk,
}

impl<'a, 'r> System<'a> for DrawRenderables<'r> {
    type SystemData = (
        ReadStorage<'a, Position>,
        ReadStorage<'a, Renderable>,
        ReadExpect<'a, map::Map>,
    );

    fn run(&mut self, (positions, renderables, map): Self::SystemData) {
        let mut y = 0;
        let mut x = 0;
        for (idx, tile) in map.tiles.iter().enumerate() {
            // Render a tile depending upon the tile type

            if map.revealed_tiles[idx] {
                let glyph;
                let mut fg;
                match tile {
                    map::TileType::Floor => {
                        glyph = rltk::to_cp437('.');
                        fg = rltk::RGB::from_f32(0.0, 0.5, 0.5);
                    }
                    map::TileType::Wall => {
                        glyph = rltk::to_cp437('#');
                        fg = rltk::RGB::from_f32(0., 1.0, 0.);
                    }
                }
                if !map.visible_tiles[idx] {
                    fg = fg.to_greyscale()
                }
                self.ctx
                    .set(x, y, fg, rltk::RGB::from_f32(0., 0., 0.), glyph);
            }

            // Move the coordinates
            x += 1;
            if x > map::MAPWIDTH as i32 - 1 {
                x = 0;
                y += 1;
            }
        }

        for (pos, render) in (&positions, &renderables).join() {
            let idx = map.xy_idx(pos.x, pos.y);
            if map.visible_tiles[idx] {
                self.ctx
                    .set(pos.x, pos.y, render.fg, render.bg, render.glyph);
            }
        }
    }
}
