#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#include "flag.h"
#include "item.h"
#include "predicate.h"

bool predicate_fulfilled(Game *g, Predicate *p) {
  switch (p->type) {
  case PREDICATE_TRUE:
    return true;
  case PREDICATE_IN_ROOM:
    return strcmp(g->current_room->name, p->argument) == 0;
  case PREDICATE_ITEM_HERE:
    return find_item(g->items, p->argument)->location == g->current_room;
  case PREDICATE_ITEM_NOT_HERE:
    return find_item(g->items, p->argument)->location != g->current_room;
  case PREDICATE_HAS_ITEM:
    return find_item(g->items, p->argument)->in_inventory;
  case PREDICATE_FLAG_ENABLED:
    return flag_value(g->flags, p->argument) > 0;
  default:
    printf("Invalid predicate type\n");
    return false;
  }
}

Predicate *create_predicate(Game *g, const char *string) {
  Predicate *p = malloc(sizeof(Predicate));
  char *buffer = malloc(strlen(string) + 1);
  strcpy(buffer, string);
  char *strtok_guy;

  char *token = strtok_r(buffer, "(", &strtok_guy);
  if (strcmp(token, "*") == 0) {
    p->type = PREDICATE_TRUE;
  } else if (strcmp(token, "IN") == 0) {
    p->type = PREDICATE_IN_ROOM;
    token = strtok_r(NULL, ")", &strtok_guy);
    p->argument = malloc(strlen(token) + 1);
    strcpy(p->argument, token);
  } else if (strcmp(token, "ITEM_HERE") == 0) {
    p->type = PREDICATE_ITEM_HERE;
    token = strtok_r(NULL, ")", &strtok_guy);
    p->argument = malloc(strlen(token) + 1);
    strcpy(p->argument, token);
  } else if (strcmp(token, "ITEM_NOT_HERE") == 0) {
    p->type = PREDICATE_ITEM_HERE;
    token = strtok_r(NULL, ")", &strtok_guy);
    p->argument = malloc(strlen(token) + 1);
    strcpy(p->argument, token);
  } else if (strcmp(token, "HAS_ITEM") == 0) {
    p->type = PREDICATE_HAS_ITEM;
    token = strtok_r(NULL, ")", &strtok_guy);
    p->argument = malloc(strlen(token) + 1);
    strcpy(p->argument, token);
  } else if (strcmp(token, "ENABLED") == 0) {
    p->type = PREDICATE_FLAG_ENABLED;
    token = strtok_r(NULL, ")", &strtok_guy);
    p->argument = malloc(strlen(token) + 1);
    strcpy(p->argument, token);
  } else {
    printf("Invalid predicate %s\n", token);
  }

  free(buffer);
  return p;
}

void print_predicate(Predicate *p) {
  switch (p->type) {
  case PREDICATE_TRUE:
    printf("*");
    break;
  case PREDICATE_IN_ROOM:
    printf("IN(%s)", p->argument);
    break;
  case PREDICATE_ITEM_HERE:
    printf("ITEM_HERE(%s)", p->argument);
    break;
  case PREDICATE_ITEM_NOT_HERE:
    printf("ITEM_NOT_HERE(%s)", p->argument);
    break;
  case PREDICATE_HAS_ITEM:
    printf("HAS_ITEM(%s)", p->argument);
    break;
  case PREDICATE_FLAG_ENABLED:
    printf("ENABLED(%s)", p->argument);
    break;
  }
}
