/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#include "poker.h"

void test_pokerInit_should_InitializePokerGame(void) {
  poker2_t poker;
  pokerInit(&poker);
  TEST_ASSERT_EQUAL_INT8(0, poker.playerCount);
  TEST_ASSERT_EQUAL_INT8(0, poker.state);
}

void test_pokerResetRound_should_ResetTheRound(void) {
  poker2_t poker;
  pokerInit(&poker);
  
  poker.potCount = 0x03;
  poker.graveSize = 0x10;
  poker.communitySize = 0x03;
  poker.deckSize = 0x0;

  pokerResetRound(&poker);

  TEST_ASSERT_NOT_EQUAL_UINT8(0, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(0, poker.graveSize);
  TEST_ASSERT_EQUAL_UINT8(0, poker.communitySize);
  TEST_ASSERT_EQUAL_UINT8(1, poker.potCount);
}

void test_pokerPotAdd_should_AddAPot(void) {
  poker2_t poker;
  pokerInit(&poker);

  TEST_ASSERT_EQUAL_UINT8(1, poker.potCount);
  TEST_ASSERT_EQUAL_UINT8(1, pokerPotAdd(&poker));
  TEST_ASSERT_EQUAL_UINT8(2, poker.potCount);
}

void test_pokerPotAdd_should_ResetThePot(void) {
  poker2_t poker;
  poker2pot_t *pot;
  uint8_t i;
  pokerInit(&poker);

  i = pokerPotAdd(&poker);
  pot = poker.pots + i;
  TEST_ASSERT_EQUAL_UINT8(0, pot->playerCount);
  TEST_ASSERT_EQUAL_INT32(0, pot->chips);
}

void test_pokerPotAddPlayer_should_AddAPlayer(void) {
  poker2_t poker;
  poker2pot_t *pot;

  pokerInit(&poker);
  pokerPlayerAdd(&poker);
  pokerPlayerAdd(&poker);

  pot = poker.pots + 0;
  TEST_ASSERT_EQUAL_UINT8(0, pot->playerCount);

  pokerPotAddPlayer(pot, 1);
  TEST_ASSERT_EQUAL_UINT8(1, pot->playerCount);
  TEST_ASSERT_EQUAL_UINT8(0x01, pot->players[0]);

  pokerPotAddPlayer(pot, 0);
  TEST_ASSERT_EQUAL_UINT8(2, pot->playerCount);
  TEST_ASSERT_EQUAL_UINT8(0x00, pot->players[1]);
}

void test_pokerPlayerAdd_should_AddAPlayer(void) {
  poker2_t poker;
  pokerInit(&poker);

  TEST_ASSERT_EQUAL_UINT8(0, poker.playerCount);
  TEST_ASSERT_EQUAL(0, pokerPlayerAdd(&poker));
  TEST_ASSERT_EQUAL_UINT8(1, poker.playerCount);
  TEST_ASSERT_EQUAL(1, pokerPlayerAdd(&poker));
  TEST_ASSERT_EQUAL_UINT8(2, poker.playerCount);
}

void test_pokerPlayerAdd_should_ResetThePlayer(void) {
  poker2_t poker;
  poker2player_t *player;
  pokerInit(&poker);

  player = poker.players + pokerPlayerAdd(&poker);
  TEST_ASSERT_EQUAL_INT32(0, player->chips);
  TEST_ASSERT_EQUAL_UINT8(0, player->state);
  TEST_ASSERT_EQUAL_UINT8(0, player->cardCount);
}

void test_pokerTurn_should_TurnCardsFromTheDeck(void) {
  poker2_t poker;
  pokerInit(&poker);

  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(0, poker.communitySize);

  pokerTurn(&poker, 1);
  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 1, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(1, poker.communitySize);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_ACE, poker.community[0]);

  pokerTurn(&poker, 3);
  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 4, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(4, poker.communitySize);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, poker.community[1]);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_QUEEN, poker.community[2]);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_JACK, poker.community[3]);
}

void test_pokerBurn_should_SendCardsToTheGrave(void) {
  poker2_t poker;
  pokerInit(&poker);

  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(0, poker.graveSize);

  pokerBurn(&poker, 1);
  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 1, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(1, poker.graveSize);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_ACE, poker.grave[0]);

  pokerBurn(&poker, 3);
  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 4, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(4, poker.graveSize);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, poker.grave[1]);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_QUEEN, poker.grave[2]);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_JACK, poker.grave[3]);

}

void test_pokerPlayerDeal_should_DealCardsToThePlayer(void) {
  poker2_t poker;
  uint8_t playerIndex;
  poker2player_t *player;

  pokerInit(&poker);

  playerIndex = pokerPlayerAdd(&poker);
  player = poker.players + playerIndex;

  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(0, player->cardCount);

  pokerPlayerDeal(&poker, player, 0x01);
  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 1, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(1, player->cardCount);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_ACE, player->cards[0]);

  pokerPlayerDeal(&poker, player, 0x01);
  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 2, poker.deckSize);
  TEST_ASSERT_EQUAL_UINT8(2, player->cardCount);
  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, player->cards[1]);
}

void test_pokerPlayerChipsAdd_should_AddChipsToThePlayer(void) {
  poker2_t poker;
  uint8_t playerIndex;
  poker2player_t *player;

  pokerInit(&poker);
  playerIndex = pokerPlayerAdd(&poker);
  player = poker.players + playerIndex;

  TEST_ASSERT_EQUAL_INT32(0, player->chips);
  pokerPlayerChipsAdd(player, 32);
  TEST_ASSERT_EQUAL_INT32(32, player->chips);
  pokerPlayerChipsAdd(player, 10);
  TEST_ASSERT_EQUAL_INT32(42, player->chips);
  pokerPlayerChipsAdd(player, -30);
  TEST_ASSERT_EQUAL_INT32(12, player->chips);
}

void test_pokerPlayerChipsAdd_should_TurnOutStateOff(void) {
  poker2_t poker;
  uint8_t playerIndex;
  poker2player_t *player;

  pokerInit(&poker);
  playerIndex = pokerPlayerAdd(&poker);
  player = poker.players + playerIndex;

  player->state |= POKER_PLAYER_STATE_OUT;
  TEST_ASSERT_EQUAL(true, player->state & POKER_PLAYER_STATE_OUT);
  pokerPlayerChipsAdd(player, 32);
  TEST_ASSERT_EQUAL(false, player->state & POKER_PLAYER_STATE_OUT);
}

int test_poker2() {
  UNITY_BEGIN();

  RUN_TEST(test_pokerInit_should_InitializePokerGame);
  RUN_TEST(test_pokerResetRound_should_ResetTheRound);
  RUN_TEST(test_pokerPotAdd_should_AddAPot);
  RUN_TEST(test_pokerPotAdd_should_ResetThePot);
  RUN_TEST(test_pokerPotAddPlayer_should_AddAPlayer);
  RUN_TEST(test_pokerPlayerAdd_should_ResetThePlayer);
  RUN_TEST(test_pokerTurn_should_TurnCardsFromTheDeck);
  RUN_TEST(test_pokerBurn_should_SendCardsToTheGrave);
  RUN_TEST(test_pokerPlayerDeal_should_DealCardsToThePlayer);
  RUN_TEST(test_pokerPlayerChipsAdd_should_AddChipsToThePlayer);
  RUN_TEST(test_pokerPlayerChipsAdd_should_TurnOutStateOff);

  return UNITY_END();
}