#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "game.h"
#include "input.h"
#include "log.h"
#include "util.h"
#include "word.h"
#include "flag.h"
#include "predicate.h"
#include "action.h"
#include "parse.h"
#include "item.h"

Game *game_create(void) {
  Game *g = malloc(sizeof(Game));
  g->should_close = false;

  game_load_words(g);
  game_load_flags(g);
  game_load_actions(g);
  game_load_rooms(g);
  game_load_room_ins(g);
  game_load_items(g);

  Log *log = create_log();
  g->log = log;

  Vector2 input_position = { 20, 400 };
  Input *input = create_input(input_position);
  input->log = log;
  input->input_length = 0;
  log->input = input;
  input->g = g;
  input->command = '>'; // Don't change this

  g->input = input;

  change_current_room(g, &g->rooms->rooms[0]);
  return g;
}

void free_game(Game *g) {
  free_rooms(*g->rooms);
  free_input(g->input);
  free_log(g->log);
  free(g);
}

#define INVALID_COMMAND "I don't know how to %s"
void game_handle_command(Game *g, const char *command) {
  if (strlen(command) == 0) {
    push_line_to_log(g->input->log, "?");
    return;
  }

  Action *a = find_action(g, command);
  if (a) {
    if (strcmp(a->description, "*") != 0) push_line_to_log(g->input->log, a->description);
    for (int i = 0; i < a->effects_count; i++) {
      cause_effect(g, a->effects[i]);
    }
  } else {
    char *response = malloc(strlen(INVALID_COMMAND) + strlen(command) + 1);
    sprintf(response, INVALID_COMMAND, command);
    push_line_to_log(g->input->log, response);
    free(response);
  }
  return;
}

void game_handle_input(Game *g) {
  handle_pressed_keys(g->input);
}

void game_draw(Game *g) {
  BeginDrawing();
  ClearBackground(BLACK);
  draw_log(g->log);
  draw_text(g->input);
  EndDrawing();
}

void game_run_until_close(Game *g) {
  while (!WindowShouldClose() && !g->should_close)
    {
      game_handle_input(g);
      game_draw(g);
    }
}

void change_current_room(Game *g, Room *r) {
  g->current_room = r;
  if (!r->visited) {
    push_line_to_log(g->input->log, find_room_in(g)->description);
    log_items_in_room(g, g->current_room);
  }
  r->visited = true;
}
