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

#include "dekiyaku.h"

void calculate_dekiyaku(Hand *h, Dekiyaku *d) {
  int brights = 0, ribbons = 0, ribbons_except_november = 0, blue_ribbons = 0, poetry_ribbons = 0, boar = 0, deer = 0, butterflies = 0;
  for (int i = 0; i < h->count; i++) {
    Card *card = h->cards[i];
    switch (card->type) {
    case BRIGHT: brights++; break;
    case RIBBON:
      ribbons++;
      if (card->month != NOVEMBER) ribbons_except_november++;
      switch (card->ribbon_type) {
      case RIBBON_BLUE: blue_ribbons++; break;
      case RIBBON_POETRY: poetry_ribbons++; break;
      default: break;
      }
      break;
    case ANIMAL:
      switch (card->month) {
      case JUNE: butterflies++; break;
      case JULY: boar++; break;
      case OCTOBER: deer++; break;
      default: break;
      }
      break;
    case CHAFF:
      break;
    }
  }

  d->count = 0;

  if (brights == 5) {
    d->meld[d->count].type = FIVE_BRIGHTS;
    d->meld[d->count].value = 12;
    d->count++;
  }

  if (brights == 4) {
    d->meld[d->count].type = FOUR_BRIGHTS;
    d->meld[d->count].value = 10;
    d->count++;
  }

  if (ribbons_except_november >= 7) {
    d->meld[d->count].type = SEVEN_RIBBONS;
    d->meld[d->count].value = 3 + ribbons; // Include november ribbons in this count
    d->count++;
  }

  if (poetry_ribbons == 3) {
    d->meld[d->count].type = POETRY_RIBBONS;
    d->meld[d->count].value = 7;
    d->count++;
  }

  if (blue_ribbons == 3) {
    d->meld[d->count].type = BLUE_RIBBONS;
    d->meld[d->count].value = 7;
    d->count++;
  }

  if (boar == 1 && deer == 1 && butterflies == 1) {
    d->meld[d->count].type = BOAR_DEER_BUTTERFLIES;
    d->meld[d->count].value = 7;
    d->count++;
  }
}

char *meld_name(DekiyakuMeldType d) {
  switch (d) {
  case FIVE_BRIGHTS:
    return "5B";
  case FOUR_BRIGHTS:
    return "4B";
  case SEVEN_RIBBONS:
    return "7R";
  case POETRY_RIBBONS:
    return "PS";
  case BLUE_RIBBONS:
    return "BS";
  case BOAR_DEER_BUTTERFLIES:
    return "ISK";
  default:
    return "None";
  }
}

int dekiyaku_value(Dekiyaku *d) {
  int value = 0;
  for (int i = 0; i < d->count; i++) {
    value += d->meld[i].value;
  }
  return value;
}

void dekiyaku_to_string(Dekiyaku *d, char *str) {
  char meld_str[200];

  strcpy(str, "Dekiyaku: ");
  for (int i = 0; i < d->count; i++) {
    sprintf(meld_str, "%s (%d) + ", meld_name(d->meld[i].type), d->meld[i].value);
    strcat(str, meld_str);
  }

  if (d->count == 0) strcat(str, "none (0)");
  else {
    str[strlen(str) - 2] = '=';
    sprintf(meld_str, "%d", dekiyaku_value(d));
    strcat(str, meld_str);
  }
}

int dekiyaku_score(Dekiyaku *d) {
  int score = 0;
  for (int i = 0; i < d->count; i++) {
    score += d->meld[i].value;
  }
  return score;
}