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

#include "bet.h"

// Done
void pokerBetInit(pokerbet_t *bet) {
  bet->blindBig = POKER_BET_BLIND_BIG_DEFAULT;
  bet->blindSmall = POKER_BET_BLIND_SMALL_DEFAULT;
}

// Done
void pokerBetReset(pokerbet_t *bet) {
  bet->pot = 0;
  bet->currentBet = 0;
}

// Not needed
uint8_t pokerBetGetRoundPlayerDefault(uint8_t roundSmallBlind) {
  return (roundSmallBlind + 1) % POKER_PLAYER_COUNT;
}

// Done
void pokerBetPlayer(pokerbet_t *bet, pokerplayer_t *player, int32_t chips) {
  bet->pot += chips;
  player->chips -= chips;
  player->currentBet += chips;
  bet->currentBet = mathMax(bet->currentBet, player->currentBet);
}

// Doneish
void pokerBetResetBetter(
  pokerbet_t *bet, pokerplayer_t *players, uint8_t roundSmallBlind
) {
  uint8_t i;
  pokerplayer_t *player;

  // Reset the round betting state.
  for(i = 0; i < POKER_PLAYER_COUNT; i++) {
    player = players + i;
    player->state = flagOff(player->state, POKER_PLAYER_STATE_ROUND_MOVE);
  }

  // Now reset to the first player that needs to bet.

  // We do this step first to reset the better
  bet->better = pokerBetGetRoundPlayerDefault(roundSmallBlind);

  // Then we check who's remaining. We do this because the default better may
  // have folded already.
  bet->better = pokerBetGetRemainingPlayer(bet, players, roundSmallBlind);
}

// Doneish
bool pokerBetPlayerCanBet(pokerbet_t *bet, pokerplayer_t *player) {
  // Is the player out?
  if(!pokerPlayerIsInRound(player)) return false;

  // Is the player broke?
  if(player->chips <= 0) return false;

  // Does the player still need to act yet?
  if(player->state & POKER_PLAYER_STATE_ROUND_MOVE) {
    if(player->currentBet >= bet->currentBet) return false;
  }

  return true;
}

uint8_t pokerBetGetRemainingPlayer(
  pokerbet_t *bet, pokerplayer_t *players, uint8_t roundSmallBlind
) {
  uint8_t def, j, pi;
  def = bet->better;

  // Now check for any remaining players
  for(j = 0; j < POKER_PLAYER_COUNT; j++) {
    pi = ((def + j) % POKER_PLAYER_COUNT);
    if(!pokerBetPlayerCanBet(bet, players + pi)) continue;
    return pi;
  }
  return 0xFF;
}

uint8_t pokerBetGetRemainingPlayerCount(pokerbet_t *bet,pokerplayer_t *players){
  uint8_t i, c;
  c = 0;
  for(i = 0; i < POKER_PLAYER_COUNT; i++) {
    if(!pokerBetPlayerCanBet(bet, players + i)) continue;
    c++;
  }
  return c;
}

void pokerBetTakeBlinds(
  pokerbet_t *bet, pokerplayer_t *players,
  uint8_t roundSmallBlind, uint8_t roundBigBlind
) {
  pokerBetPlayer(bet, players + roundSmallBlind, bet->blindSmall);
  pokerBetPlayer(bet, players + roundBigBlind, bet->blindBig);
}