#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define EMPTY '_'
#define MAX_LENGTH 100
#define NUM_LETTERS 26
#define NUM_POOLS 2

//my functions
void input_vocab_words();
void input_pool_characters();
void init_board();
int taken_placement();
int out_of_bounds();
int invalid_char();
int row_srch();
int col_srch();
void winner_prompt();


void print_enter_pool_character()
{
    printf("Enter new character for the pool\n");
}

char get_new_pool_character()
{ // Receives a new character from the user to insert to the pool, and returns this character
    char c;
    scanf(" %c",&c);
    return c;
}

void print_board(char** board,int size)
{ //Print the current state of the given board of size sizeXsize
    printf("Current Board:\n");
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            printf("| %c |", board[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}


void prompt_vocab_words()
{
    printf("Enter Vocabulary Words: \n");
}

void get_word_for_vocab(char* word_address)
{ //Receives a single word for the vocabulary from the user, and saves it in the address passed as parameter
    scanf("%s",word_address);
}

void print_scores(int score1,int score2)
{ //Prints the current scores of both players. 'score1' is the score of player 1, 'score2' is the score of player 2
    printf("Player 1 Score: %d\nPlayer 2 Score: %d\n", score1,score2);
}



int input_game_constant(char* prompt)
{ //Recevies from the user a single
    printf("%s\n",prompt);
    int value;
    while (1) {

        if (scanf("%d", &value) != 1) {
            // If scanf fails, clear the input buffer

            scanf("%*s");
            printf("Invalid input. Please Re-enter.\n");
        }
        else if (value < 1)
        {
            printf("Invalid input. Please Re-enter.\n");
        }
        else {
            return value;
        }
    }

}


int input_game_size()
{
    return input_game_constant("Enter Board Size");
}

int input_pool_size()
{
    return input_game_constant("Enter Character Pool Size");
}

int input_time_limit()
{
    return input_game_constant("Enter Game Time Limit");
}

int input_score_limit()
{
    return input_game_constant("Enter Game Score Limit");
}

void get_turn_inputs(char* turn_character_ptr,int* row_idx_ptr, int* col_idx_ptr)
{
    scanf(" %c %d %d",turn_character_ptr,row_idx_ptr,col_idx_ptr);
}

void prompt_turn_player(int player_idx)
{
    printf("Player %d, Enter Turn character, board row and board column:\n",player_idx);
}

void start_game_prompt()
{
    printf("************** !Welcome To The Scrabbles Game **************\n");
}




void print_pool(char* pool1, char* pool2,int pool_size)
{
    printf("Current Pools:\n");
    printf("Pool1: ");
    for (int i = 0; i < pool_size; i++)
        printf(" %c,",pool1[i]);
    printf("\n");
    printf("Pool2: ");
    for (int i = 0; i < pool_size; i++)
        printf(" %c,",pool2[i]);
    printf("\n");

}



void invalid_turn_character_choice()
{
    printf("Invalid Choice! Character not available to you.\nPlease Re-enter:\n");
}
void taken_turn_placement_choice()
{
    printf("Invalid Choice! Placement choice taken.\nPlease Re-enter:\n");
}
void out_of_bounds_turn_choice()
{
    printf("Invalid Choice! Placement Out Of Board Bounds.\nPlease Re-enter:\n");
}

void print_achieved_score(int score)
{
    printf("Achieved Score: %d!\n", score);
}

void print_winner(int player_idx,int score)
{
    printf("Player %d Wins! Score: %d", player_idx, score);
}

void print_tie(int score)
{
    printf("Tie! Score: %d",score);
}


int get_vocab_size()
{
    int size;
    printf("Enter Vocabulary Size: \n");
    scanf("%d", &size);
    return size;
}

void prompt_pool_character_input(int player_idx)
{//Prompt player <player_idx> to provide character to insert to his pool
    printf("Enter Characters For Pool %d\n",player_idx);

}
///////////////////////////////////////////////////////////////////////////////
int main()
{
    start_game_prompt();
    //intializing game settings
    int N = input_game_size();
    int L = input_pool_size();
    int T = input_time_limit();
    int S = input_score_limit();

    //intializing vocab words
    //  initialize vocab words array
    //      1 Allocate memory for the row pointers
    int n = get_vocab_size();
    char** vocab_words = malloc(sizeof(char*) * N);

    //      2 Allocate memory for each row
    for (int i = 0; i < N; i++) {
        vocab_words[i] = malloc(sizeof(char) * MAX_LENGTH);
    }
    prompt_vocab_words();
    input_vocab_words(vocab_words, n);


    //input pool characters
    char* pool1 = malloc(sizeof(char) * L);
    char* pool2 = malloc(sizeof(char) * L);

    prompt_pool_character_input(1);
    input_pool_characters(pool1, L);

    prompt_pool_character_input(2);
    input_pool_characters(pool2, L);


    //initialize board
    //1 Allocate memory for the row pointers
    char** board = malloc(sizeof(char*) * N);

    //2 Allocate memory for each row
    for (int i = 0; i < N; i++) {
        board[i] = malloc(sizeof(char) * N);
    }
    init_board(board, N);

    //setting the game
    int score1 = 0, score2 = 0;
    int player_idx = 1;
    int turn = 0;

    //game start
    while(turn < T && score1 < S && score2 < S){
        print_board(board, N);
        print_pool(pool1, pool2, L);
        print_scores(score1, score2);
        int row_idx, col_idx;
        char turn_character;
        int idx;

        prompt_turn_player(player_idx);
        get_turn_inputs(&turn_character, &row_idx, &col_idx);
        //check input
        while(invalid_char(&turn_character, &player_idx, pool1, pool2, L, &idx)){
            get_turn_inputs(&turn_character, &row_idx, &col_idx);
        }

        while(out_of_bounds(&row_idx, &col_idx, N)){
            get_turn_inputs(&turn_character, &row_idx, &col_idx);
        }

        while(taken_placement(&row_idx, &col_idx, board)){
            get_turn_inputs(&turn_character, &row_idx, &col_idx);
        }

        // update pool
        print_enter_pool_character();
        char new_char = get_new_pool_character();
        player_idx == 1 ? (pool1[idx] = new_char) : (pool2[idx] = new_char);

        // update board
        board[row_idx][col_idx] = turn_character;

        // search for words and calc score
        row_srch(vocab_words, n, board, N, row_idx, col_idx);
        col_srch(vocab_words, n, board, N, row_idx, col_idx);

        
        //next turn
        player_idx = 3 - player_idx;
        turn++;
    }
    
    winner_prompt(score1, score2);
    
    return 0;
}

///////////////////////////////////////////////////////////////////////////////
//----------------------------My Functions--------------------------------------

void input_vocab_words(char** arr, int word_num){
    for(int i=0; i<word_num; i++){
        scanf("%s", arr[i]);
    }
}


void input_pool_characters(char* pool, int L) {
    for (int i = 0; i < L; i++) {
        scanf(" %c", &pool[i]);
    }
}


void init_board(char** board, int N){
    for(int i=0; i<N; i++){
        for(int j=0; j<N; j++){
            board[i][j] = EMPTY;
        }
    }
}


int invalid_char(char* turn_character_ptr, int* player_idx, char* pool1, char* pool2, int L, int* char_idx){
    if (*player_idx == 1) {
        for (int i = 0; i < L; i++) {
            if (pool1[i] == *turn_character_ptr) {
                *char_idx = i;
                return 0;
            }
        }
    } else {
        for (int i = 0; i < L; i++) {
            if (pool2[i] == *turn_character_ptr) {
                *char_idx = i;
                return 0;
            }
        }
    }
    invalid_turn_character_choice();
    return 1;
}

int out_of_bounds(int* row_idx_ptr, int* col_idx_ptr, int N){
    if(*row_idx_ptr>N-1 || *row_idx_ptr<0 ||*col_idx_ptr>N-1 || *col_idx_ptr<0){
        out_of_bounds_turn_choice();
        return 1;
    }
    return 0;

}

int taken_placement(int* row_idx_ptr, int* col_idx_ptr,char** board){
    if(board[*row_idx_ptr][*col_idx_ptr] == EMPTY){
        return 0;
    }
    taken_turn_placement_choice();
    return 1;
}

int strcmpr(char *str1, char *str2) {
    int i = 0; int score = 0;
    while (str1[i] != '\0'){
        if (str1[i] != str2[i]){
            return -1;
        }
        i++;
        score += (str1[i] - 'a')%7;
    }
    return score;
}

int row_srch(char** vocab_words, int n, char** board, int N, int row_idx, int col_idx) {
    int score = 0;
    // Perform word search horizontally (left to right) in the specified row
    char row_word[MAX_LENGTH];

    int startCol = col_idx;
    while (startCol > 0 && board[row_idx][startCol - 1] != EMPTY) {
        startCol--;
    }
    
    int length = 0;
    for (int j = startCol; j < N && board[row_idx][j] != EMPTY; j++) {
        row_word[length] = board[row_idx][j];
        length++;
    row_word[length] = '\0';
    }
    for (int i = 0; i < n; i++) {
        if(strcmpr(row_word, vocab_words[i])>0){
            score += strcmpr(row_word, vocab_words[i]);
        }
    }
    return score;
}

int col_srch(char** vocab_words, int n, char** board, int N, int row_idx, int col_idx) {
    int score = 0;
    // Perform word search vertically (top to bottom) in the specified column
    char col_word[MAX_LENGTH];

    int startRow = row_idx;
    while (startRow > 0 && board[startRow - 1][col_idx] != EMPTY) {
        startRow--;
    }

    int length = 0;
    for (int i = startRow; i < N && board[i][col_idx] != EMPTY; i++) {
        col_word[length] = board[i][col_idx];
        length++;
    col_word[length] = '\0';
    }
    
    for (int j = 0; j < n; j++) {
        if(strcmpr(col_word, vocab_words[j])> 0) {
            score += strcmpr(col_word, vocab_words[j]);
        }
    }
    return score;
}

void winner_prompt(int score1, int score2){
    if(score1 == score2) print_tie(score1);
    else if(score1 > score2) print_winner(1, score1);
    else print_winner(2, score2);
}