//
// Created by m on 12/3/21.
//

#include "visualizer.hpp"

bool Visualizer::update(InputResult input) {
    if(input.keycode == KEY_ESCAPE) {
        return true;
    }
    switch(input.keycode) {
        case KEY_RIGHT: x += 1; break;
        case KEY_LEFT: x -= 1; break;
        case KEY_UP: y -= 1; break;
        case KEY_DOWN: y += 1; break;
        default: break;
    }

    this->x = std::clamp(this->x, 0, (int)this->tile_map.get_width()-1);
    this->y = std::clamp(this->y, 0, (int)this->tile_map.get_height()-1);
    this->camera.move_camera(Point{x,y});

    return false;
}

void Visualizer::render(Renderer *renderer) {
    SpriteSheet tiles = SpriteSheet{"sprites/map1.bmp", TILE_WIDTH, TILE_HEIGHT};
    SpriteSheet characters = SpriteSheet{"sprites/character.bmp", TILE_WIDTH, TILE_HEIGHT, COLOR_BLACK};
    auto grass = Sprite{&tiles, 0};
    auto wall = Sprite{&tiles, 497};
    auto character = Sprite{&characters, this->sprite_index};
    auto bounds = this->camera.get_bounds();

    for(int ty : ranges::views::iota(bounds.y, bounds.y+bounds.height)) {
        for(int tx : ranges::views::iota(bounds.x, bounds.x+bounds.width)) {
            auto wp = camera.camera_coords_to_screen_coords(Point{tx, ty});
            int wx = wp.x, wy = wp.y;
            if(this->tile_map.get(tx, ty) == FLOOR_CHAR) {
                renderer->draw_sprite(grass, wx*TILE_WIDTH, wy*TILE_HEIGHT);
            }
            else {
                renderer->draw_sprite(wall, wx*TILE_WIDTH, wy*TILE_HEIGHT);
            }
            if(tx == x && ty == y) {
                renderer->draw_sprite(character, wx*TILE_WIDTH, wy*TILE_HEIGHT);
            }
        }
    }
    return; // for breaking
}

void Visualizer::initialize(GameInitArgs args) {
    this->window_width = args.window_width;
    this->window_height = args.window_height;
    int tilesx = (window_width / TILE_WIDTH)+1;
    int tilesy = (window_height / TILE_HEIGHT)+1;
    initialize_map(MAP_SIZE_W, MAP_SIZE_H);
    this->camera = Camera(Point{x,y}, tilesx, tilesy, tile_map.get_width(), tile_map.get_height());
}

void Visualizer::initialize_map(int width, int height) {
    this->tile_map = Grid2D<char>(width, height);
    for(int ty=0;ty<this->tile_map.get_height();ty++) {
        for (int tx = 0; tx < tile_map.get_width(); tx++) {
            this->tile_map.insert(tx, ty, FLOOR_CHAR);
        }
    }
}

Visualizer::~Visualizer() = default;
