#include <string.h>
#include <stdio.h>

#include "game.h"
#include "card.h"
#include "teyaku.h"
#include "dekiyaku.h"

Vector2 mouse_pos;
char teyaku_calculation[400];
char dekiyaku_calculation[400];

void initialize_game(Game *g) {
  g->deck.count = 0;
  g->should_close = false;
  g->state = GAME_STATE_INITIALIZING;
  for (int i = 0; i < 48; i++) {
    CardType t = CHAFF;
    RibbonType rt = RIBBON_NONE;
    Month month = i / 4;
    switch (i) {
    case 0:
    case 8:
    case 28:
    case 40:
    case 44:
      t = BRIGHT; break;
    case 1:
    case 5:
    case 9:
      t = RIBBON; rt = RIBBON_POETRY; break;
    case 21:
    case 33:
    case 37:
      t = RIBBON; rt = RIBBON_BLUE; break;
    case 13:
    case 17:
    case 25:
    case 42:
      t = RIBBON; rt = RIBBON_PLAIN; break;
    case 4:
    case 12:
    case 16:
    case 20:
    case 24:
    case 29:
    case 32:
    case 36:
    case 41:
      t = ANIMAL; break;
    }
    g->cards[i] = (Card) { i, t, rt, month, (Vector2) { 800, 100 }, false, false };
    g->cards[i].move.end_time = 0.;
    g->cards[i].move.position = &g->cards[i].position;
    g->deck.cards[i] = &g->cards[i];
    g->deck.count++;
  }

  shuffle_hand(&g->deck);

  g->player_hand.count = 0;
  g->player_hand.position = (Vector2) { 20, 450 };
  g->right_hand.count = 0;
  g->right_hand.position = (Vector2) { 20, 100 };
  g->left_hand.count = 0;
  g->left_hand.position = (Vector2) { 20, 300 };

  strcpy(teyaku_calculation, "");
  strcpy(dekiyaku_calculation, "");

  Image cards_image = LoadImage("img/cards.png");
  g->cards_texture = LoadTextureFromImage(cards_image);
  UnloadImage(cards_image);
  g->state = GAME_STATE_DEALING;
}

bool stale_calculation = true;
void handle_input(Game *g) {
  if (IsMouseButtonPressed(0)) {
    mouse_pos = GetMousePosition();
    for (int i = 0; i < 48; i++) {
      if (point_within_card(&g->cards[i], mouse_pos)) {
	g->cards[i].selected = !g->cards[i].selected;
	stale_calculation = true;
	break;
      }
    }
  }
}

void run_calculation(Game *g) {
  int num_selected = 0;
  if (stale_calculation) {
    Hand h;
    h.count = 0;
    for (int i = 0; i < 48; i++) {
      num_selected += g->cards[i].selected;
      if (g->cards[i].selected) h.cards[h.count++] = &g->cards[i];
    }

    if (num_selected == 7) {
      Teyaku t;
      calculate_teyaku(h, &t);
      teyaku_to_string(&t, teyaku_calculation);
    } else {
      strcpy(teyaku_calculation, "");
    }

    Dekiyaku d;
    calculate_dekiyaku(h, &d);
    dekiyaku_to_string(&d, dekiyaku_calculation);
    stale_calculation = false;
  }
}

void run_frame_dealing(Game *g) {
  if (g->player_hand.count < 4) {
    deal(&g->deck, &g->player_hand, 4, true);
  } else if (g->right_hand.count < 4) {
    deal(&g->deck, &g->right_hand, 4, false);
  } else if (g->left_hand.count < 4) {
    deal(&g->deck, &g->left_hand, 4, false);
  } else if (g->player_hand.count < 7) {
    deal(&g->deck, &g->player_hand, 3, true);
  } else if (g->right_hand.count < 7) {
    deal(&g->deck, &g->right_hand, 3, false);
  } else if (g->left_hand.count < 7) {
    deal(&g->deck, &g->left_hand, 3, false);
  } else {
    g->state = GAME_STATE_INITIALIZING;
  }
}

void run_frame(Game *g) {
  float delta = GetFrameTime();
  bool done_moving = true;
  for (int i = 0; i < 48; i++) {
    move_position(&g->cards[i].move, delta);
    if (!card_done_moving(&g->cards[i])) done_moving = false;
  }
  if (!done_moving) return;

  handle_input(g);

  switch (g->state) {
  case GAME_STATE_INITIALIZING:
    return;
  case GAME_STATE_DEALING:
    run_frame_dealing(g);
    break;
  }
  run_calculation(g);
}

void draw_frame(Game *g) {
  BeginDrawing();
  ClearBackground(RAYWHITE);
  for (int i = 0; i < 48; i++) {
    draw_card(&g->cards[i], &g->cards_texture);
  }

  DrawText(teyaku_calculation, 10, 550, 25, BLACK);
  DrawText(dekiyaku_calculation, 10, 500, 25, BLACK);
  EndDrawing();
}

void run_until_closing(Game *g) {
  while (!WindowShouldClose() && !g->should_close) {
    run_frame(g);
    draw_frame(g);
  }
}