#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SUITS 4
#define FACES 13
#define HAND_SIZE 5


void shuffel(int deck[][FACES]);

void deal(int deck[][FACES], const char* face[], const char* suit[], int row1[], int col1[]);

int containsPair(int handCol[], int replace[]);
int containsTwoPairs(int handCol[], int replace[]);
int containsThreeOfKind(int handCol[], int replace[]);
int containsFourOfKind(int handCol[], int replace[]);
int containsFlush(int handRow[], int replace[]);
int containsStraight(int handCol[], int replace[]);
int containsFullHouse(int handCol[]);

int evaluateHand(int handRow[], int handCol[]);
char* getHandName(int rank);

int cardsToReplace(int rank);

void markCardsToReplace(int handRow[], int handCol[],int rank, int replace[]);

void replaceCards(int deck[][FACES], int row1[],int col1[], int replace[]);



int main(void)
{
    int deck[SUITS][FACES] = { 0 };

    int row1[HAND_SIZE], col1[HAND_SIZE];
    int replace[HAND_SIZE] = { 0 };

    const char* suit[SUITS] = {"Hearts", "Diamonds", "Clubs", "Spades"};

    const char* face[FACES] = {"Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King"};

    srand(time(NULL));

    shuffel(deck);

    
    deal(deck, face, suit, row1, col1);

    int rank1 = evaluateHand(row1, col1);

    printf("Dealer's initial hand: Face down\n");

    
    markCardsToReplace(row1, col1, rank1, replace);

    int number = cardsToReplace(rank1);

    printf("Initial hand category: %s\n", getHandName(rank1));
    printf("Number of cards to replace: %d\n", number);

    replaceCards(deck, row1, col1, replace);

    
    int newRank = evaluateHand(row1, col1);

    printf("\nDealer's final hand category: %s\n",
        getHandName(newRank));

    printf("Dealer's final hand:\n");

    for (int i = 0; i < HAND_SIZE; i++)
    {
        printf("%s of %s\n",
            face[col1[i]], suit[row1[i]]);
    }

   
}

void shuffel(int deck[][FACES])
{
    for (int card = 1; card <= 52; card++)
    {
        int row;
        int column;

        do
        {
            row = rand() % SUITS;
            column = rand() % FACES;
        } while (deck[row][column] != 0);

        deck[row][column] = card;
    }
}



void deal(int deck[][FACES], const char* face[], const char* suit[], int row1[], int col1[])
{
    (void)face;
    (void)suit;

    for (int card = 1; card <= HAND_SIZE; card++)
    {
        for (int row = 0; row < SUITS; row++)
        {
            for (int column = 0; column < FACES; column++)
            {
                if (deck[row][column] == card)
                {
                    row1[card - 1] = row;
                    col1[card - 1] = column;
                }
            }
        }
    }
}


int containsPair(int handCol[], int replace[])
{
    int count[FACES] = { 0 };
    int pairs = 0;

    for (int i = 0; i < HAND_SIZE; i++)
        count[handCol[i]]++;

    for (int i = 0; i < FACES; i++)
    {
        if (count[i] == 2)
            pairs++;
    }

    if (pairs != 1)
        return 0;

    if (replace != NULL)
    {
        for (int i = 0; i < HAND_SIZE; i++)
        {
            if (count[handCol[i]] == 2)
                replace[i] = 0;
            else
                replace[i] = 1;
        }
    }

    return 1;
}


int containsTwoPairs(int handCol[], int replace[])
{
    int count[FACES] = { 0 };
    int pairs = 0;

    for (int i = 0; i < HAND_SIZE; i++)
        count[handCol[i]]++;

    for (int i = 0; i < FACES; i++)
    {
        if (count[i] == 2)
            pairs++;
    }

    if (pairs != 2)
        return 0;

    if (replace != NULL)
    {
        for (int i = 0; i < HAND_SIZE; i++)
        {
            if (count[handCol[i]] == 2)
                replace[i] = 0;
            else
                replace[i] = 1;
        }
    }

    return 1;
}



int containsThreeOfKind(int handCol[], int replace[])
{
    int count[FACES] = { 0 };
    int threeOfKind = 0;

    for (int i = 0; i < HAND_SIZE; i++)
        count[handCol[i]]++;

    for (int i = 0; i < FACES; i++)
    {
        if (count[i] == 3)
        {
            threeOfKind = 1;
            break;
        }
    }

    if (threeOfKind == 0)
        return 0;

    if (replace != NULL)
    {
        for (int i = 0; i < HAND_SIZE; i++)
        {
            if (count[handCol[i]] == 3)
                replace[i] = 0;
            else
                replace[i] = 1;
        }
    }

    return 1;
}



int containsFourOfKind(int handCol[], int replace[])
{
    int count[FACES] = { 0 };
    int fourOfKind = 0;

    for (int i = 0; i < HAND_SIZE; i++)
        count[handCol[i]]++;

    for (int i = 0; i < FACES; i++)
    {
        if (count[i] == 4)
        {
            fourOfKind = 1;
            break;
        }
    }

    if (fourOfKind == 0)
        return 0;

    if (replace != NULL)
    {
        for (int i = 0; i < HAND_SIZE; i++)
        {
            if (count[handCol[i]] == 4)
                replace[i] = 0;
            else
                replace[i] = 1;
        }
    }

    return 1;
}



int containsFlush(int handRow[], int replace[])
{
    for (int i = 1; i < HAND_SIZE; i++)
    {
        if (handRow[i] != handRow[0])
            return 0;
    }

    if (replace != NULL)
    {
        for (int i = 0; i < HAND_SIZE; i++)
            replace[i] = 0;
    }

    return 1;
}



int containsStraight(int handCol[], int replace[])
{
    int temp[HAND_SIZE];

    for (int i = 0; i < HAND_SIZE; i++)
        temp[i] = handCol[i];

   
    for (int i = 0; i < HAND_SIZE; i++)
    {
        for (int j = 0; j < HAND_SIZE - i - 1; j++)
        {
            if (temp[j] > temp[j + 1])
            {
                int swap = temp[j];
                temp[j] = temp[j + 1];
                temp[j + 1] = swap;
            }
        }
    }

    int straight = 1;

    for (int i = 0; i < HAND_SIZE - 1; i++)
    {
        if (temp[i + 1] != temp[i] + 1)
        {
            straight = 0;
            break;
        }
    }

    

    if (straight == 0)
        return 0;

    if (replace != NULL)
    {
        for (int i = 0; i < HAND_SIZE; i++)
            replace[i] = 0;
    }

    return 1;
}



int containsFullHouse(int handCol[])
{
    int count[FACES] = { 0 };
    int hasThree = 0;
    int hasPair = 0;

    for (int i = 0; i < HAND_SIZE; i++)
        count[handCol[i]]++;

    for (int i = 0; i < FACES; i++)
    {
        if (count[i] == 3)
            hasThree = 1;
        else if (count[i] == 2)
            hasPair = 1;
    }

    return hasThree && hasPair;
}



int evaluateHand(int handRow[], int handCol[])
{
    int flush = containsFlush(handRow, NULL);
    int straight = containsStraight(handCol, NULL);

    if (flush && straight)
        return 8;

    if (containsFourOfKind(handCol, NULL))
        return 7;

    if (containsFullHouse(handCol))
        return 6;

    if (flush)
        return 5;

    if (straight)
        return 4;

    if (containsThreeOfKind(handCol, NULL))
        return 3;

    if (containsTwoPairs(handCol, NULL))
        return 2;

    if (containsPair(handCol, NULL))
        return 1;

    return 0;
}



char* getHandName(int rank)
{
    switch (rank)
    {
    case 8: return "Straight Flush";
    case 7: return "Four of a Kind";
    case 6: return "Full House";
    case 5: return "Flush";
    case 4: return "Straight";
    case 3: return "Three of a Kind";
    case 2: return "Two Pairs";
    case 1: return "One Pair";
    default: return "High Card";
    }
}



int cardsToReplace(int rank)
{
    if (rank == 0) return 3;
    if (rank == 1) return 3;
    if (rank == 2) return 1;
    if (rank == 3) return 2;

    return 0;
}



void markCardsToReplace(int handRow[], int handCol[],int rank, int replace[])
{
    for (int i = 0; i < HAND_SIZE; i++)
        replace[i] = 0;

    if (cardsToReplace(rank) == 0)
        return;

    if (rank == 1)
    {
        containsPair(handCol, replace);
    }
    else if (rank == 2)
    {
        containsTwoPairs(handCol, replace);
    }
    else if (rank == 3)
    {
        containsThreeOfKind(handCol, replace);
    }
    else if (rank == 0)
    {
        
        for (int i = 0; i < HAND_SIZE; i++)
            replace[i] = 1;

        int best1 = -1;
        int best2 = -1;

        for (int i = 0; i < HAND_SIZE; i++)
        {
            int value = handCol[i];

            
            if (value == 0)
                value = 13;

            if (best1 == -1)
            {
                best1 = i;
            }
            else
            {
                int value1 = handCol[best1];

                if (value1 == 0)
                    value1 = 13;

                if (value > value1)
                {
                    best2 = best1;
                    best1 = i;
                }
                else if (best2 == -1)
                {
                    best2 = i;
                }
                else
                {
                    int value2 = handCol[best2];

                    if (value2 == 0)
                        value2 = 13;

                    if (value > value2)
                        best2 = i;
                }
            }
        }

        replace[best1] = 0;
        replace[best2] = 0;
    }

    (void)handRow;
}



void replaceCards(int deck[][FACES], int row1[],int col1[], int replace[])
{
    int nextCard = HAND_SIZE + 1;

    for (int i = 0; i < HAND_SIZE; i++)
    {
        if (replace[i] == 1)
        {
            int found = 0;

            while (nextCard <= 52 && !found)
            {
                for (int row = 0; row < SUITS && !found; row++)
                {
                    for (int column = 0; column < FACES; column++)
                    {
                        if (deck[row][column] == nextCard)
                        {
                            row1[i] = row;
                            col1[i] = column;
                            found = 1;
                            break;
                        }
                    }
                }

                nextCard++;
            }
        }
    }
}