#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"
#include "flag.h"
#include "effect.h"
#include "room_in.h"

void cause_effect(Game *g, Effect *e) {
  if (e == NULL) return;

  switch (e->type) {
  case EFFECT_NOOP:
    break;
  case EFFECT_GOTO:
    change_current_room(g, find_room(g->rooms, e->argument));
    break;
  case EFFECT_INCREMENT:
    find_flag(g->flags, e->argument)->value++;
    break;
  case EFFECT_DECREMENT:
    find_flag(g->flags, e->argument)->value--;
    break;
  case EFFECT_ENABLE:
    find_flag(g->flags, e->argument)->value = 1;
    break;
  case EFFECT_DISABLE:
    find_flag(g->flags, e->argument)->value = 0;
    break;
  case EFFECT_QUIT_GAME:
    g->should_close = true;
    break;
  case EFFECT_LOOK_ROOM:
    push_line_to_log(g->input->log, find_room_in(g)->description);
    log_items_in_room(g, g->current_room);
    break;
  case EFFECT_TAKE_ITEM:
    take_item(g, e->argument);
    break;
  case EFFECT_DROP_ITEM:
    drop_item(g, e->argument);
    break;
  case EFFECT_DESTROY_ITEM:
    destroy_item(g, e->argument);
    break;
  case EFFECT_CHECK_INVENTORY:
    check_inventory(g);
    break;
  }
}

Effect *create_effect(Game *g, const char *string) {
  Effect *e = malloc(sizeof(Effect));
  char *buffer = malloc(strlen(string) + 1);
  strcpy(buffer, string);

  char *strtok_guy;
  char *token = strtok_r(buffer, "(", &strtok_guy);
  if (token == NULL) {
    e->type = EFFECT_NOOP;
  } else {
    if (strcmp(token, "GOTO") == 0) {
      e->type = EFFECT_GOTO;
    } else if (strcmp(token, "INCREMENT") == 0) {
      e->type = EFFECT_INCREMENT;
    } else if (strcmp(token, "DECREMENT") == 0) {
      e->type = EFFECT_DECREMENT;
    } else if (strcmp(token, "ENABLE") == 0) {
      e->type = EFFECT_ENABLE;
    } else if (strcmp(token, "DISABLE") == 0) {
      e->type = EFFECT_DISABLE;
    } else if (strcmp(token, "QUIT_GAME") == 0) {
      e->type = EFFECT_QUIT_GAME;
    } else if (strcmp(token, "LOOK_ROOM") == 0) {
      e->type = EFFECT_LOOK_ROOM;
    } else if (strcmp(token, "TAKE") == 0) {
      e->type = EFFECT_TAKE_ITEM;
    } else if (strcmp(token, "DROP") == 0) {
      e->type = EFFECT_DROP_ITEM;
    } else if (strcmp(token, "DESTROY") == 0) {
      e->type = EFFECT_DESTROY_ITEM;
    } else if (strcmp(token, "CHECK_INVENTORY") == 0) {
      e->type = EFFECT_CHECK_INVENTORY;
    } else {
      printf("Unknown effect %s\n", token);
    }

    token = strtok_r(NULL, ")", &strtok_guy);
    if (token) {
      e->argument = malloc(strlen(token) + 1);
      strcpy(e->argument, token);
    }
  }

  free(buffer);
  return e;
}

void print_effect(Effect *e) {
  switch (e->type) {
  case EFFECT_NOOP:
    printf("*");
    break;
  case EFFECT_GOTO:
    printf("GOTO(%s)", e->argument);
    break;
  case EFFECT_INCREMENT:
    printf("INCREMENT(%s)", e->argument);
    break;
  case EFFECT_DECREMENT:
    printf("DECRMENT(%s)", e->argument);
    break;
  case EFFECT_ENABLE:
    printf("ENABLE(%s)", e->argument);
    break;
  case EFFECT_DISABLE:
    printf("DISABLE(%s)", e->argument);
    break;
  case EFFECT_QUIT_GAME:
    printf("QUIT_GAME()");
    break;
  case EFFECT_LOOK_ROOM:
    printf("LOOK_ROOM()");
    break;
  case EFFECT_TAKE_ITEM:
    printf("TAKE(%s)", e->argument);
    break;
  case EFFECT_DROP_ITEM:
    printf("DROP(%s)", e->argument);
    break;
  case EFFECT_DESTROY_ITEM:
    printf("DESTROY(%s)", e->argument);
    break;
  case EFFECT_CHECK_INVENTORY:
    printf("CHECK_INVENTORY()");
    break;
  }
}
