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

#include "PokerPot.hpp"
#include "PokerGame.hpp"
#include "PokerPlayer.hpp"

using namespace Dawn;

void PokerPotWinning::award() {
  auto it = this->winners.begin();
  while(it != this->winners.end()) {
    if(it == this->winners.begin()) {
      (*it)->addChips(this->chipsEach + this->chipsOverflow);
    } else {
      (*it)->addChips(this->chipsEach);
    }
    ++it;
  }
}

struct PokerPotWinning PokerPot::getWinners(PokerGame *game) {
  struct PokerPotWinning winning;

  winning.pot = this;
  
  // Calculate the winnings first.
  auto it = this->players.begin();
  while(it != this->players.end()) {
    auto player = *it;

    if(player->isOut || player->isFolded) {
      ++it;
      continue;
    }

    winning.participants.push_back(player);
    winning.winnings[player] = player->getWinning();
    ++it;
  }

  // Compare participating players
  auto it2 = winning.participants.begin();
  while(it2 != winning.participants.end()) {
    auto playerLeft = *it2;
    auto winnerLeft = &winning.winnings[playerLeft];
    bool_t isWinner = true;
    enum CardValue highNumber = CARD_VALUE_INVALD;
    enum CardValue number = CARD_VALUE_INVALD;
    struct Card highCard(0xFF);
    struct Card card(0xFF);

    auto it3 = winning.participants.begin();
    while(it3 != winning.participants.end()) {
      if(it2 == it3) {
        ++it3;
        continue;
      }

      auto playerRight = *it3;
      auto winnerRight = &winning.winnings[playerRight];

      // Am I the better hand / Is it the better hand?
      if(winnerLeft->type < winnerRight->type) {
        ++it3;
        continue;
      }
      if(winnerLeft->type > winnerRight->type) {
        isWinner = false;
        break;
      }

      // Equal, compare hands.
      card = PokerWinning::compare(winnerLeft, winnerRight);
      if(card.cardValue == 0xFF) {
        isWinner = false;
        break;
      }

      // Determine high card.
      number = card.getValue();
      if(
        highNumber == CARD_VALUE_INVALD ||
        number == CARD_ACE ||
        number > highNumber
      ) {
        highCard = card;
        highNumber = number;
      }
      ++it3;
    }

    if(!isWinner) {
      ++it2;
      continue;
    }

    winnerLeft->kicker = highCard;
    winning.winners.push_back(playerLeft);
    ++it2;
  }

  winning.chipsEach = this->chips / (int32_t)winning.winners.size();
  winning.chipsOverflow = this->chips - (
    winning.chipsEach * (int32_t)winning.winners.size()
  );

  return winning;
}