#include <stdio.h>
#include <stdlib.h>
#include "card.h"

static Vector2 card_size = (Vector2) { CARD_WIDTH, CARD_HEIGHT };
static char *month_english_abbr[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

void draw_card(Card *c, Texture2D *cards_texture) {
  int i_vert = c->index % 4;
  int i_horiz = c->index / 4;
  int pos_vert = i_vert * CARD_HEIGHT;
  int pos_horiz = i_horiz * CARD_WIDTH;

  if (c->visible) {
    DrawTexturePro(
		   *cards_texture,
		   (Rectangle) { pos_horiz, pos_vert, CARD_WIDTH, CARD_HEIGHT },
		   (Rectangle) { c->position.x, c->position.y, card_size.x, card_size.y },
		   (Vector2) { 0, 0 },
		   0.,
		   RAYWHITE
		   );
  } else {
    DrawRectangleRec((Rectangle) { c->position.x, c->position.y, card_size.x, card_size.y }, BLACK);
  }

  if (c->selected) {
    DrawCircle(c->position.x + 10, c->position.y + 10, 10, BLUE);
  }
}

bool point_within_card(Card *c, Vector2 point) {
  return point.x > c->position.x && point.x < c->position.x + card_size.x &&
    point.y > c->position.y && point.y < c->position.y + card_size.y;
}

void shuffle_hand(Hand *h) {
  Card *swap;
  for (int i = h->count - 1; i >= 0; i--) {
    int index = rand() % (i + 1);
    swap = h->cards[i];
    h->cards[i] = h->cards[index];
    h->cards[index] = swap;
  }
}

void order_deck(Hand *h) {
  Card *swap;

  swap = h->cards[1];
  h->cards[1] = h->cards[47-0];
  h->cards[47-0] = swap;

  swap = h->cards[5];
  h->cards[5] = h->cards[47-1];
  h->cards[47-1] = swap;

  swap = h->cards[9];
  h->cards[9] = h->cards[47-2];
  h->cards[47-2] = swap;

  swap = h->cards[0];
  h->cards[0] = h->cards[47-12];
  h->cards[47-12] = swap;

  swap = h->cards[4];
  h->cards[4] = h->cards[47-13];
  h->cards[47-13] = swap;

  swap = h->cards[8];
  h->cards[8] = h->cards[47-14];
  h->cards[47-14] = swap;
}

void remove_from_hand(Hand *h, Card *c) {
  bool card_found = false;
  for (int i = 0; i < h->count - 1; i++) {
    if (h->cards[i] == c) card_found = true;
    if (card_found) h->cards[i] = h->cards[i + 1];
  }
  h->count--;
}

int first_open_spot(Hand *h) {
  int order_guy[48];
  int order_guy_count = 0;

  for (int i = 0; i < 48; i++) {
    order_guy[i] = 0;
  }

  for (int i = 0; i < h->count; i++) {
    if (h->cards[i] == NULL) continue;
    order_guy[h->cards[i]->order] = 1;
    order_guy_count++;
  }

  int fos = h->count;
  for (int i = 0; i < order_guy_count; i++) {
    if (order_guy[i]) continue; 
    fos = i;
    break;
  }
  return fos;
}

void add_to_hand(Hand *h, Card *c, float deal_speed) {
  c->order = first_open_spot(h);
  h->cards[h->count] = c;

  c->move.position = &c->position;
  c->move.origin.x = c->position.x;
  c->move.origin.y = c->position.y;
  switch (h->display_type) {
  case HAND_DISPLAY_ROW:
    c->move.destination.x = h->position.x + (c->order * (CARD_WIDTH + 10));
    c->move.destination.y = h->position.y;
    break;
  case HAND_DISPLAY_FIELD:
    c->move.destination.x = h->position.x + ((c->order / 2) * (CARD_WIDTH + 10));
    c->move.destination.y = h->position.y + (c->order % 2 * (CARD_HEIGHT + 10));
    break;
  case HAND_DISPLAY_DECK:
    c->move.destination.x = h->position.x;
    c->move.destination.y = h->position.y;
    break;
  case HAND_DISPLAY_SCORED:
    c->move.destination.x = h->position.x + (c->order * (CARD_WIDTH - 30));
    c->move.destination.y = h->position.y;
    break;
  }
  c->move.curve = CURVE_EASE_IN_OUT;
  c->move.current_time = 0.;
  c->move.end_time = deal_speed;

  h->count++;
}

bool card_done_moving(Card *c) {
  return c->move.current_time > c->move.end_time;
}

void deal(Hand *from, Hand *to, int count, bool up, float deal_speed) {
  for (int i = 0; i < count; i++) {
    Card *c = from->cards[from->count - 1];
    c->visible = up;
    add_to_hand(to, c, deal_speed);
    from->count--;
  }
}

Rectangle next_card_position(Hand *h) {
  int i = first_open_spot(h);
  return (Rectangle) {
    h->position.x + ((i / 2) * (CARD_WIDTH + 10)),
    h->position.y + (i % 2 * (CARD_HEIGHT + 10)),
    CARD_WIDTH,
    CARD_HEIGHT
  };
}