#include "game.h"
Game * game;
int game_starting_level = 35;
Game* game_global(void) {
    return game;
}
int blocks_count(void) {
    int n = 0;
    n += land_array_count(game->blocks->fixed);
    n += land_array_count(game->blocks->dynamic);
    n += land_array_count(game->blocks->transparent);
    return n;
}
void game_setup(float w, float h) {
    Game * self;
    land_alloc(self);
    self->viewport = viewport_new(w, h);
    self->level = 0;
    self->blocks = blocks_new();
    self->menu = menu_new();
    self->overview = overview_new();
    editor_new();
    game = self;
}
void game_del(Game * self) {
    if (! self) {
        return ;
    }
    if (self->blocks) {
        blocks_destroy(self->blocks);
    }
    data_teardown();
    overview_destroy(game->overview);
    land_free(self->viewport);
    land_free(self->menu);
    land_free(self);
    editor_del();
}
int game_neighboring_level(int level, int gox, int goz) {
    int row = (level - 1) / 7;
    int col = (level - 1) % 7;
    col += gox + 7;
    row += goz + 7;
    col %= 7;
    row %= 7;
    level = 1 + row * 7 + col;
    return level;
}
void game_level_number_to_xz(int level, int * x, int * z) {
    * z = (level - 1) / 7;
    * x = (level - 1) % 7;
}
void game_level_done(Game * self, int gox, int goz) {
    Application * a = app();
    if (land_equals(self->state, "play")) {
        self->gox = gox;
        self->goz = goz;
        if (! a->test) {
            // Save the level (with the player on the exit, so if
            // re-loaded this level shows them immediately
            save_level(0, 1);
        }
        self->state = "done";
        self->state_tick = self->ticks;
        if (self->skunk) {
            self->ex = self->skunk->x;
            self->ez = self->skunk->z;
        }
        self->level = game_neighboring_level(self->level, gox, goz);
        sound(Data_teleport, 1);
    }
}
void game_recalc(void) {
    game->blocks->rebuild_static_cache = 1;
    game->blocks->rebuild_dynamic_cache = 1;
}
void game_key(Game * self, int k) {
    menu_key(k, land_key(LandKeyLeftShift) || land_key(LandKeyRightShift));
}
void add_death(void) {
    sound(Data_oh_no, 1);
    game->state = "died";
    game->deaths++;
    game->deaths_per_minute [0]++;
}
void game_tick(Game * self) {
    Application * a = app();
    Render * r = render_global();
    if (land_equals(self->state, "done") || land_equals(self->state, "died")) {
        if (self->ticks > self->state_tick + 30) {
            a->load_after_redraw = 1;
            a->find_entrance = 1;
            if (game->level == 28) {
                r->song = 2 /* elephant theme */;
            }
            play_song();
            if (land_equals(self->state, "died")) {
                return ;
            }
        }
    }
    if (a->load_after_redraw) {
        return ;
    }
    input_tick();
    if (controls.pressed [ControlMenu]) {
        input_toggle_pause();
    }
    if (a->overview) {
        overview_tick(game->overview);
        return ;
    }
    if (land_key_pressed(LandKeyTab)) {
        a->show_map = ! a->show_map;
    }
    if (a->show_map) {
        if (land_key_pressed(LandKeyBack)) {
            a->show_map = 0;
        }
        if (controls.pressed [ControlLeft]) {
            main_switch_to_title(0);
        }
        if (controls.pressed [ControlRight]) {
            input_toggle_pause();
        }
        if (controls.pressed [ControlJump]) {
            input_toggle_pause();
        }
        return ;
    }
    if (land_equals(self->state, "play")) {
        if (self->skunk) {
            if (((Skunk *) self->skunk)->dead || self->skunk->y < - 960) {
                add_death();
            }
        }
        if (self->elephant) {
            if (self->elephant->y < - 960) {
                add_death();
            }
        }
    }
    if (land_key_pressed(' ')) {
        if (game->orchid && game->orchid->talk) {
            game->orchid->speech = 600;
        }
        if (game->skunk && game->skunk->talk) {
            game->skunk->speech = 600;
        }
        if (game->elephant && game->elephant->talk) {
            game->elephant->speech = 600;
        }
        if (game->gnome && game->gnome->talk) {
            game->gnome->speech = 600;
        }
    }
    if (land_key_pressed(LandKeyBack)) {
        main_switch_to_title(0);
    }
    if (land_key_pressed(LandKeyMenu)) {
        main_switch_to_title(1);
    }
    if (! a->editor) {
        a->time++;
        int m = a->time / 60 / 60;
        if (m > game->first_minute) {
            count_seen();
            for (int i = 0; i < 29; i += 1) {
                game->deaths_per_minute [29 - i] = game->deaths_per_minute [28 - i];
                game->levels_in_minute [29 - i] = game->levels_in_minute [28 - i];
            }
            game->deaths_per_minute [0] = 0;
            game->levels_in_minute [0] = game->seen;
            game->first_minute = m;
        }
        {
            LandArrayIterator __iter0__ = LandArrayIterator_first(self->blocks->animated);
            for (Block * b = LandArrayIterator_item(self->blocks->animated, &__iter0__); LandArrayIterator_next(self->blocks->animated, &__iter0__); b = LandArrayIterator_item(self->blocks->animated, &__iter0__)) {
                b->block_type->tick(b);
            }
        }
    }
    self->ticks += 1;
}
