/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */
#pragma once
#include <dawn/dawn.h>
#include "../util/array.h"

/**
 * Returns the suit of a given card.
 * @param card to get the suit for.
 * @returns The suit.
 */
#define cardGetSuit(card) (card / CARD_COUNT_PER_SUIT)

/**
 * Returns the number of a given card.
 * @param card The card to get the number for.
 * @returns The card number.
 */
#define cardGetNumber(card) (card % CARD_COUNT_PER_SUIT)

/**
 * Returns the card number for a given suit.
 * @param number The number to get.
 * @param suit The suit to get.
 * @returns The card for this suit and number combo.
 */
#define cardGet(number, suit) ((suit * CARD_COUNT_PER_SUIT) + number)

/**
 * Deals a card from an array source to an array destination. Pointers to array
 * lengths will be updated.
 * 
 * @param source Array source.
 * @param sourceSize Pointer to where the count of cards is being stored.
 * @param dest Array destination.
 * @param destSize Pointer to the size of the destination array.
 */
void cardDeal(card_t *source, uint8_t *sourceSize, card_t *dest,
  uint8_t *destSize
);

/**
 * Sort a hand of cards. Cards are ordered in descending weight, aces are high.
 * Cards will be grouped by their suits, e.g. CARD_CLUBS_TWO will appear before
 * CARD_DIAMONDS_KING.
 * 
 * @param cards Hand of cards to sort.
 * @param length Length of the array of cards.
 */
void cardHandSort(card_t *cards, uint8_t length);
int32_t _cardSorter(const void* left, const void* right);

/**
 * Check if an array of cards contains a specific card.
 * 
 * @param hand Hand/Array of cards to check.
 * @param length Length of the array of cards.
 * @param card Card to look for
 * @returns The index within the array that the card is. -1 if not found.
 */
int32_t cardContains(card_t *hand, uint8_t length, card_t card);

/**
 * Check if the array of cards contains a specific number.
 * 
 * @param hand Array of cards to check
 * @param length Length of the array.
 * @param number The number to look for.
 * @returns The index within the array that the first card is. -1 if not found.
 */
int32_t cardContainsNumber(card_t *hand, uint8_t length, uint8_t number);

/**
 * Counts the amount of times a card's number appears within the given hand.
 * 
 * @param in The hand to check
 * @param inCount How big the hand being checked is
 * @param number The number to look for.
 * @param out The indexes within the hand array for each card matching.
 * @return How many cards in the pair, e.g. 3 for Three of a kind, 4 for full. 
 */
uint8_t cardCountPairs(
  card_t *in, uint8_t inCount, uint8_t number, int32_t out[4]
);

/**
 * Shuffles a hand / deck
 * 
 * @param hand Hand to shuffle.
 * @param length Length of the hand to shuffle.
 */
void cardShuffle(card_t *hand, uint8_t length);